diff --git a/build.gradle.kts b/build.gradle.kts index dcf9eb7d..cc4ff994 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,27 +1,29 @@ plugins { id("ru.mipt.npm.gradle.project") + kotlin("multiplatform") apply false kotlin("jvm") apply false kotlin("js") apply false kotlin("jupyter.api") apply false + id("ru.mipt.npm.gradle.js") apply false } -val dataforgeVersion by extra("0.4.0-dev-2") -val kotlinWrappersVersion by extra("pre.148-kotlin-1.4.30") -val fxVersion by extra("14") +val dataforgeVersion by extra("0.4.0") +val kotlinWrappersVersion by extra("pre.152-kotlin-1.4.32") +val fxVersion by extra("11") allprojects { repositories { - mavenLocal() mavenCentral() jcenter() maven("https://repo.kotlin.link") - maven("https://kotlin.bintray.com/kotlin-js-wrappers") maven("https://dl.bintray.com/pdvrieze/maven") - maven("http://maven.jzy3d.org/releases") + maven("https://maven.jzy3d.org/releases") + maven("https://maven.pkg.jetbrains.space/kotlin/p/kotlin/kotlin-js-wrappers") + maven("https://maven.pkg.jetbrains.space/public/p/kotlinx-html/maven") } group = "space.kscience" - version = "0.2.0-dev-13" + version = "0.2.0-dev-15" } subprojects { diff --git a/demo/gdml/build.gradle.kts b/demo/gdml/build.gradle.kts index ae64890e..e4fef51e 100644 --- a/demo/gdml/build.gradle.kts +++ b/demo/gdml/build.gradle.kts @@ -2,8 +2,7 @@ import ru.mipt.npm.gradle.DependencyConfiguration import ru.mipt.npm.gradle.FXModule plugins { - kotlin("multiplatform") - id("ru.mipt.npm.gradle.common") + id("ru.mipt.npm.gradle.mpp") application } diff --git a/demo/gdml/src/commonTest/kotlin/space/kscience/visionforge/gdml/GDMLVisualTest.kt b/demo/gdml/src/commonTest/kotlin/space/kscience/visionforge/gdml/GDMLVisualTest.kt index c0587c2e..c12c7215 100644 --- a/demo/gdml/src/commonTest/kotlin/space/kscience/visionforge/gdml/GDMLVisualTest.kt +++ b/demo/gdml/src/commonTest/kotlin/space/kscience/visionforge/gdml/GDMLVisualTest.kt @@ -3,12 +3,12 @@ package space.kscience.visionforge.gdml import space.kscience.dataforge.meta.string import space.kscience.dataforge.names.toName import space.kscience.dataforge.values.asValue -import space.kscience.visionforge.gdml.GdmlShowcase.cubes +import space.kscience.gdml.GdmlShowCase import space.kscience.visionforge.setProperty import space.kscience.visionforge.solid.SolidMaterial import kotlin.test.Test import kotlin.test.assertEquals -import kotlin.test.assertTrue +import kotlin.test.assertNotNull class GDMLVisualTest { @@ -23,10 +23,10 @@ class GDMLVisualTest { @Test fun testPrototypeProperty() { - val visual = cubes.toVision() - val child = visual["composite[0,0,0].segment[0]".toName()] - assertTrue { child!= null } - child?.setProperty(SolidMaterial.MATERIAL_COLOR_KEY, "red".asValue()) - assertEquals("red", child?.getProperty(SolidMaterial.MATERIAL_COLOR_KEY).string) + val vision = GdmlShowCase.cubes().toVision() + val child = vision["composite-000.segment-0".toName()] + assertNotNull(child) + child.setProperty(SolidMaterial.MATERIAL_COLOR_KEY, "red".asValue()) + assertEquals("red", child.getProperty(SolidMaterial.MATERIAL_COLOR_KEY).string) } } \ No newline at end of file diff --git a/demo/gdml/src/jsMain/kotlin/space/kscience/visionforge/gdml/demo/GdmlJsDemoApp.kt b/demo/gdml/src/jsMain/kotlin/space/kscience/visionforge/gdml/demo/GdmlJsDemoApp.kt index f1cbec0d..1b40155e 100644 --- a/demo/gdml/src/jsMain/kotlin/space/kscience/visionforge/gdml/demo/GdmlJsDemoApp.kt +++ b/demo/gdml/src/jsMain/kotlin/space/kscience/visionforge/gdml/demo/GdmlJsDemoApp.kt @@ -4,9 +4,9 @@ import kotlinx.browser.document import react.child import react.dom.render import space.kscience.dataforge.context.Global +import space.kscience.gdml.GdmlShowCase import space.kscience.visionforge.Application import space.kscience.visionforge.bootstrap.useBootstrap -import space.kscience.visionforge.gdml.GdmlShowcase import space.kscience.visionforge.gdml.toVision import space.kscience.visionforge.solid.three.ThreePlugin import space.kscience.visionforge.startApplication @@ -19,13 +19,13 @@ private class GDMLDemoApp : Application { val element = document.getElementById("app") ?: error("Element with id 'app' not found on page") - val context = Global.context("demo") .apply{ - plugins.fetch(ThreePlugin) + val context = Global.buildContext("demo"){ + plugin(ThreePlugin) } render(element) { child(GDMLApp) { - val vision = GdmlShowcase.cubes.toVision() + val vision = GdmlShowCase.cubes().toVision() //println(context.plugins.fetch(VisionManager).encodeToString(vision)) attrs { this.context = context diff --git a/demo/gdml/src/jvmMain/kotlin/space/kscience/visionforge/gdml/demo/GdmlFxDemoApp.kt b/demo/gdml/src/jvmMain/kotlin/space/kscience/visionforge/gdml/demo/GdmlFxDemoApp.kt index 544d8a7f..4fd1e2e7 100644 --- a/demo/gdml/src/jvmMain/kotlin/space/kscience/visionforge/gdml/demo/GdmlFxDemoApp.kt +++ b/demo/gdml/src/jvmMain/kotlin/space/kscience/visionforge/gdml/demo/GdmlFxDemoApp.kt @@ -3,12 +3,13 @@ package space.kscience.visionforge.gdml.demo import javafx.geometry.Orientation import javafx.scene.Parent import javafx.stage.FileChooser -import space.kscience.dataforge.context.Global +import space.kscience.dataforge.context.Context +import space.kscience.dataforge.context.fetch +import space.kscience.gdml.GdmlShowCase import space.kscience.visionforge.VisionManager import space.kscience.visionforge.describedProperties import space.kscience.visionforge.editor.VisualObjectEditorFragment import space.kscience.visionforge.editor.VisualObjectTreeFragment -import space.kscience.visionforge.gdml.GdmlShowcase.cubes import space.kscience.visionforge.gdml.toVision import space.kscience.visionforge.solid.FX3DPlugin import space.kscience.visionforge.solid.FXCanvas3D @@ -19,8 +20,13 @@ import tornadofx.* class GDMLDemoApp : App(GDMLView::class) class GDMLView : View() { - private val fx3d = Global.plugins.fetch(FX3DPlugin) - private val visionManager = Global.plugins.fetch(VisionManager) + private val context = Context { + plugin(FX3DPlugin) + plugin(VisionManager) + } + + private val fx3d = context.fetch(FX3DPlugin) + private val visionManager = context.fetch(VisionManager) private val canvas = FXCanvas3D(fx3d) private val treeFragment = VisualObjectTreeFragment().apply { @@ -61,7 +67,7 @@ class GDMLView : View() { init { runAsync { - cubes.toVision() + GdmlShowCase.cubes().toVision() } ui { canvas.render(it) } diff --git a/demo/jupyter-playground/build.gradle.kts b/demo/jupyter-playground/build.gradle.kts index e467f49b..903b991b 100644 --- a/demo/jupyter-playground/build.gradle.kts +++ b/demo/jupyter-playground/build.gradle.kts @@ -7,9 +7,6 @@ plugins { repositories { mavenCentral() maven("https://repo.kotlin.link") - maven("https://dl.bintray.com/mipt-npm/dataforge") - maven("https://dl.bintray.com/mipt-npm/kscience") - maven("https://dl.bintray.com/mipt-npm/dev") } dependencies { diff --git a/demo/jupyter-playground/src/main/kotlin/hep/dataforge/playground/VisionForgePlayGroundForJupyter.kt b/demo/jupyter-playground/src/main/kotlin/hep/dataforge/playground/VisionForgePlayGroundForJupyter.kt index 7b277b71..e1e2a97f 100644 --- a/demo/jupyter-playground/src/main/kotlin/hep/dataforge/playground/VisionForgePlayGroundForJupyter.kt +++ b/demo/jupyter-playground/src/main/kotlin/hep/dataforge/playground/VisionForgePlayGroundForJupyter.kt @@ -8,19 +8,17 @@ import kotlinx.html.unsafe import org.jetbrains.kotlinx.jupyter.api.HTML import org.jetbrains.kotlinx.jupyter.api.annotations.JupyterLibrary import org.jetbrains.kotlinx.jupyter.api.libraries.* +import space.kscience.dataforge.context.Context import space.kscience.dataforge.misc.DFExperimental import space.kscience.gdml.Gdml import space.kscience.plotly.Plot import space.kscience.visionforge.Vision -import space.kscience.visionforge.VisionForge import space.kscience.visionforge.gdml.toVision import space.kscience.visionforge.html.HtmlVisionFragment import space.kscience.visionforge.html.Page import space.kscience.visionforge.html.embedVisionFragment -import space.kscience.visionforge.html.fragment +import space.kscience.visionforge.plotly.PlotlyPlugin import space.kscience.visionforge.plotly.toVision -import space.kscience.visionforge.plotly.usePlotly -import space.kscience.visionforge.plugins import space.kscience.visionforge.solid.Solids import space.kscience.visionforge.visionManager @@ -28,6 +26,11 @@ import space.kscience.visionforge.visionManager @DFExperimental internal class VisionForgePlayGroundForJupyter : JupyterIntegration() { + private val context = Context("VisionForge") { + plugin(Solids) + plugin(PlotlyPlugin) + } + private val jsBundle = ResourceFallbacksBundle(listOf( ResourceLocation("js/visionforge-playground.js", ResourcePathType.CLASSPATH_PATH)) ) @@ -39,22 +42,17 @@ internal class VisionForgePlayGroundForJupyter : JupyterIntegration() { val id = "visionforge.vision[${counter++}]" div { this.id = id - embedVisionFragment(VisionForge.visionManager, fragment = fragment) + embedVisionFragment(context.visionManager, fragment = fragment) } script { type = "text/javascript" - unsafe { +"VisionForge.renderVisionsAt(\"$id\");" } + unsafe { +"window.renderAllVisionsById(\"$id\");" } } } override fun Builder.onLoaded() { resource(jsResource) - onLoaded { - VisionForge.plugins.fetch(Solids) - VisionForge.usePlotly() - } - import( "space.kscience.gdml.*", "space.kscience.plotly.*", @@ -65,17 +63,15 @@ internal class VisionForgePlayGroundForJupyter : JupyterIntegration() { "space.kscience.visionforge.html.page" ) - import() - render { gdmlModel -> - val fragment = VisionForge.fragment { + val fragment = HtmlVisionFragment { vision(gdmlModel.toVision()) } HTML(produceHtmlVisionString(fragment)) } render { vision -> - val fragment = VisionForge.fragment { + val fragment = HtmlVisionFragment { vision(vision) } @@ -83,7 +79,7 @@ internal class VisionForgePlayGroundForJupyter : JupyterIntegration() { } render { plot -> - val fragment = VisionForge.fragment { + val fragment = HtmlVisionFragment { vision(plot.toVision()) } diff --git a/demo/muon-monitor/build.gradle.kts b/demo/muon-monitor/build.gradle.kts index 209685b9..3fe03042 100644 --- a/demo/muon-monitor/build.gradle.kts +++ b/demo/muon-monitor/build.gradle.kts @@ -22,6 +22,7 @@ kotlin { tasks.getByName("jvmProcessResources") { dependsOn(jsBrowserDistribution) + duplicatesStrategy = DuplicatesStrategy.EXCLUDE afterEvaluate { from(jsBrowserDistribution) } @@ -57,6 +58,12 @@ application { mainClass.set("ru.mipt.npm.muon.monitor.server.MMServerKt") } +tasks.withType(){ + kotlinOptions{ + freeCompilerArgs = freeCompilerArgs + "-Xir-property-lazy-initialization" + } +} + //distributions { // main { // contents { diff --git a/demo/muon-monitor/src/jsMain/kotlin/ru/mipt/npm/muon/monitor/MMDemoApp.kt b/demo/muon-monitor/src/jsMain/kotlin/ru/mipt/npm/muon/monitor/MMDemoApp.kt index 1047047d..45a34e06 100644 --- a/demo/muon-monitor/src/jsMain/kotlin/ru/mipt/npm/muon/monitor/MMDemoApp.kt +++ b/demo/muon-monitor/src/jsMain/kotlin/ru/mipt/npm/muon/monitor/MMDemoApp.kt @@ -26,7 +26,7 @@ private class MMDemoApp : Application { val element = document.getElementById("app") ?: error("Element with id 'app' not found on page") - val context = Global.context("demo") {} + val context = Global.buildContext("demo") {} render(element) { child(MMApp) { attrs { diff --git a/demo/muon-monitor/src/jvmMain/kotlin/ru/mipt/npm/muon/monitor/server/MMServer.kt b/demo/muon-monitor/src/jvmMain/kotlin/ru/mipt/npm/muon/monitor/server/MMServer.kt index 9e4ff43c..336264e2 100644 --- a/demo/muon-monitor/src/jvmMain/kotlin/ru/mipt/npm/muon/monitor/server/MMServer.kt +++ b/demo/muon-monitor/src/jvmMain/kotlin/ru/mipt/npm/muon/monitor/server/MMServer.kt @@ -26,6 +26,7 @@ import ru.mipt.npm.muon.monitor.sim.Cos2TrackGenerator import ru.mipt.npm.muon.monitor.sim.simulateOne import space.kscience.dataforge.context.Context import space.kscience.dataforge.context.Global +import space.kscience.dataforge.context.fetch import space.kscience.dataforge.misc.DFExperimental import space.kscience.visionforge.solid.Solids import java.awt.Desktop @@ -38,7 +39,7 @@ private val generator = Cos2TrackGenerator(JDKRandomGenerator(223)) fun Application.module(context: Context = Global) { val currentDir = File(".").absoluteFile environment.log.info("Current directory: $currentDir") - val solidManager = context.plugins.load(Solids) + val solidManager = context.fetch(Solids) install(DefaultHeaders) install(CallLogging) diff --git a/demo/playground/src/jsMain/kotlin/playgroundMain.kt b/demo/playground/src/jsMain/kotlin/playgroundMain.kt index 4ecf33f3..9ee2dc93 100644 --- a/demo/playground/src/jsMain/kotlin/playgroundMain.kt +++ b/demo/playground/src/jsMain/kotlin/playgroundMain.kt @@ -1,14 +1,10 @@ -import kotlinx.browser.window import space.kscience.dataforge.misc.DFExperimental -import space.kscience.visionforge.VisionForge -import space.kscience.visionforge.plotly.usePlotly -import space.kscience.visionforge.solid.three.useThreeJs +import space.kscience.visionforge.plotly.PlotlyPlugin +import space.kscience.visionforge.runVisionClient +import space.kscience.visionforge.solid.three.ThreePlugin @DFExperimental -fun main(): Unit = VisionForge.run{ - console.info("Starting VisionForge context") - usePlotly() - useThreeJs() - window.asDynamic()["VisionForge"] = VisionForge - renderVisionsInWindow() +fun main() = runVisionClient { + plugin(PlotlyPlugin) + plugin(ThreePlugin) } \ No newline at end of file diff --git a/demo/playground/src/jvmMain/kotlin/gdmlCubes.kt b/demo/playground/src/jvmMain/kotlin/gdmlCubes.kt index 823a8f19..9de22003 100644 --- a/demo/playground/src/jvmMain/kotlin/gdmlCubes.kt +++ b/demo/playground/src/jvmMain/kotlin/gdmlCubes.kt @@ -1,20 +1,19 @@ package space.kscience.visionforge.examples -import space.kscience.dataforge.misc.DFExperimental -import space.kscience.visionforge.VisionForge -import space.kscience.visionforge.gdml.GdmlShowcase.cubes +import space.kscience.dataforge.context.Context +import space.kscience.gdml.GdmlShowCase import space.kscience.visionforge.gdml.toVision import space.kscience.visionforge.html.ResourceLocation -import space.kscience.visionforge.html.fragment -import space.kscience.visionforge.invoke import space.kscience.visionforge.solid.Solids -@DFExperimental -fun main() = VisionForge(Solids) { - val content = VisionForge.fragment { +fun main() { + val context = Context { + plugin(Solids) + } + + context.makeVisionFile(resourceLocation = ResourceLocation.SYSTEM){ vision("canvas") { - cubes.toVision() + GdmlShowCase.cubes().toVision() } } - makeVisionFile(content, resourceLocation = ResourceLocation.SYSTEM) } \ No newline at end of file diff --git a/demo/playground/src/jvmMain/kotlin/gdmlIaxo.kt b/demo/playground/src/jvmMain/kotlin/gdmlIaxo.kt index 9ab231e6..a292396f 100644 --- a/demo/playground/src/jvmMain/kotlin/gdmlIaxo.kt +++ b/demo/playground/src/jvmMain/kotlin/gdmlIaxo.kt @@ -1,24 +1,22 @@ package space.kscience.visionforge.examples -import space.kscience.dataforge.misc.DFExperimental +import space.kscience.dataforge.context.Context import space.kscience.gdml.Gdml import space.kscience.gdml.LUnit import space.kscience.gdml.decodeFromStream -import space.kscience.visionforge.VisionForge import space.kscience.visionforge.gdml.toVision import space.kscience.visionforge.html.ResourceLocation -import space.kscience.visionforge.html.fragment -import space.kscience.visionforge.invoke import space.kscience.visionforge.solid.Solids -@DFExperimental -fun main() = VisionForge(Solids) { - val content = VisionForge.fragment { +fun main() { + val context = Context { + plugin(Solids) + } + context.makeVisionFile(resourceLocation = ResourceLocation.EMBED) { vision("canvas") { - Gdml.decodeFromStream(Gdml.javaClass.getResourceAsStream("/gdml/babyIAXO.gdml")!!, true).toVision { + Gdml.decodeFromStream(javaClass.getResourceAsStream("/gdml/babyIAXO.gdml")!!, true).toVision { lUnit = LUnit.MM } } } - makeVisionFile(content, resourceLocation = ResourceLocation.EMBED) } \ No newline at end of file diff --git a/demo/playground/src/jvmMain/kotlin/plotlyVision.kt b/demo/playground/src/jvmMain/kotlin/plotlyVision.kt index 7da3d09b..4575b952 100644 --- a/demo/playground/src/jvmMain/kotlin/plotlyVision.kt +++ b/demo/playground/src/jvmMain/kotlin/plotlyVision.kt @@ -1,17 +1,16 @@ package space.kscience.visionforge.examples -import space.kscience.dataforge.misc.DFExperimental +import space.kscience.dataforge.context.Context import space.kscience.plotly.scatter -import space.kscience.visionforge.VisionForge import space.kscience.visionforge.html.ResourceLocation -import space.kscience.visionforge.html.fragment -import space.kscience.visionforge.invoke import space.kscience.visionforge.plotly.PlotlyPlugin import space.kscience.visionforge.plotly.plotly -@DFExperimental -fun main() = VisionForge(PlotlyPlugin) { - val fragment = fragment { +fun main() { + val context = Context { + plugin(PlotlyPlugin) + } + context.makeVisionFile(resourceLocation = ResourceLocation.SYSTEM){ vision { plotly { scatter { @@ -21,5 +20,4 @@ fun main() = VisionForge(PlotlyPlugin) { } } } - makeVisionFile(fragment, resourceLocation = ResourceLocation.SYSTEM) } \ No newline at end of file diff --git a/demo/playground/src/jvmMain/kotlin/randomSpheres.kt b/demo/playground/src/jvmMain/kotlin/randomSpheres.kt index 04027052..855c99c1 100644 --- a/demo/playground/src/jvmMain/kotlin/randomSpheres.kt +++ b/demo/playground/src/jvmMain/kotlin/randomSpheres.kt @@ -1,20 +1,23 @@ package space.kscience.visionforge.examples import kotlinx.html.h1 -import space.kscience.dataforge.misc.DFExperimental -import space.kscience.visionforge.VisionForge +import space.kscience.dataforge.context.Context import space.kscience.visionforge.html.ResourceLocation -import space.kscience.visionforge.html.fragment -import space.kscience.visionforge.invoke import space.kscience.visionforge.solid.* import java.nio.file.Paths import kotlin.random.Random -@OptIn(DFExperimental::class) -fun main() = VisionForge(Solids) { +fun main() { + val context = Context { + plugin(Solids) + } val random = Random(112233) - val fragment = fragment { + + context.makeVisionFile( + Paths.get("randomSpheres.html"), + resourceLocation = ResourceLocation.EMBED + ) { h1 { +"Happy new year!" } vision { solid { @@ -33,9 +36,4 @@ fun main() = VisionForge(Solids) { } } } - makeVisionFile( - fragment, - Paths.get("randomSpheres.html"), - resourceLocation = ResourceLocation.EMBED - ) } \ No newline at end of file diff --git a/demo/playground/src/jvmMain/kotlin/serverExtensions.kt b/demo/playground/src/jvmMain/kotlin/serverExtensions.kt index da4d6cde..4dfd35f1 100644 --- a/demo/playground/src/jvmMain/kotlin/serverExtensions.kt +++ b/demo/playground/src/jvmMain/kotlin/serverExtensions.kt @@ -1,10 +1,9 @@ package space.kscience.visionforge.examples +import space.kscience.dataforge.context.Context import space.kscience.dataforge.misc.DFExperimental -import space.kscience.visionforge.Vision -import space.kscience.visionforge.VisionForge -import space.kscience.visionforge.html.HtmlVisionFragment import space.kscience.visionforge.html.ResourceLocation +import space.kscience.visionforge.html.VisionTagConsumer import space.kscience.visionforge.html.page import space.kscience.visionforge.html.scriptHeader import space.kscience.visionforge.makeFile @@ -18,25 +17,26 @@ public fun VisionServer.usePlayground(): Unit { useScript("js/visionforge-playground.js") } -@DFExperimental -public fun VisionForge.makeVisionFile( - content: HtmlVisionFragment, +@OptIn(DFExperimental::class) +public fun Context.makeVisionFile( path: Path? = null, title: String = "VisionForge page", resourceLocation: ResourceLocation = ResourceLocation.SYSTEM, show: Boolean = true, + content: VisionTagConsumer<*>.() -> Unit ): Unit { + val actualPath = page(title, content = content).makeFile(path) { actualPath -> mapOf("threeJs" to scriptHeader("js/visionforge-playground.js", resourceLocation, actualPath)) } if (show) Desktop.getDesktop().browse(actualPath.toFile().toURI()) } -@DFExperimental -public fun VisionForge.makeVisionFile( - vision: Vision, - path: Path? = null, - title: String = "VisionForge page", - resourceLocation: ResourceLocation = ResourceLocation.SYSTEM, - show: Boolean = true, -): Unit = makeVisionFile({ vision(vision) }, path, title, resourceLocation, show) +//@DFExperimental +//public fun Context.makeVisionFile( +// vision: Vision, +// path: Path? = null, +// title: String = "VisionForge page", +// resourceLocation: ResourceLocation = ResourceLocation.SYSTEM, +// show: Boolean = true, +//): Unit = makeVisionFile({ vision(vision) }, path, title, resourceLocation, show) diff --git a/demo/playground/src/jvmMain/kotlin/simpleCube.kt b/demo/playground/src/jvmMain/kotlin/simpleCube.kt index 3a90cfb8..e98d1ff1 100644 --- a/demo/playground/src/jvmMain/kotlin/simpleCube.kt +++ b/demo/playground/src/jvmMain/kotlin/simpleCube.kt @@ -1,22 +1,21 @@ package space.kscience.visionforge.examples -import space.kscience.dataforge.misc.DFExperimental -import space.kscience.visionforge.VisionForge +import space.kscience.dataforge.context.Context import space.kscience.visionforge.html.ResourceLocation -import space.kscience.visionforge.html.fragment -import space.kscience.visionforge.invoke import space.kscience.visionforge.solid.Solids import space.kscience.visionforge.solid.box import space.kscience.visionforge.solid.solid -@DFExperimental -fun main() = VisionForge(Solids) { - val content = fragment { +fun main() { + val context = Context { + plugin(Solids) + } + + context.makeVisionFile(resourceLocation = ResourceLocation.SYSTEM){ vision("canvas") { solid { box(100, 100, 100) } } } - makeVisionFile(content, resourceLocation = ResourceLocation.SYSTEM) } \ No newline at end of file diff --git a/demo/plotly-fx/build.gradle.kts b/demo/plotly-fx/build.gradle.kts new file mode 100644 index 00000000..fa7a6976 --- /dev/null +++ b/demo/plotly-fx/build.gradle.kts @@ -0,0 +1,57 @@ +plugins { + kotlin("multiplatform") + application + id("org.openjfx.javafxplugin") version "0.0.9" +} + +repositories { + maven("https://repo.kotlin.link") + mavenLocal() + jcenter() +} + +kotlin { + jvm { + withJava() + } + + js(IR) { + browser() + } + + sourceSets{ + commonMain{ + dependencies { + + } + } + val jvmMain by getting { + dependencies { + implementation("no.tornado:tornadofx:1.7.19") + implementation(project(":visionforge-server")) + implementation("ch.qos.logback:logback-classic:1.2.3") + } + } + } + +} + +javafx { + modules("javafx.web") + version = "16" +} + +application { + mainClassName = "space.kscience.plotly.fx.PlotlyFXAppKt" +} + + +// +//val compileKotlin: KotlinCompile by tasks +//compileKotlin.kotlinOptions { +// jvmTarget = "11" +//} +//val compileTestKotlin: KotlinCompile by tasks +//compileTestKotlin.kotlinOptions { +// jvmTarget = "11" +//} \ No newline at end of file diff --git a/demo/sat-demo/src/main/kotlin/ru/mipt/npm/sat/satServer.kt b/demo/sat-demo/src/main/kotlin/ru/mipt/npm/sat/satServer.kt index 6651cc13..6d80c691 100644 --- a/demo/sat-demo/src/main/kotlin/ru/mipt/npm/sat/satServer.kt +++ b/demo/sat-demo/src/main/kotlin/ru/mipt/npm/sat/satServer.kt @@ -15,7 +15,7 @@ import space.kscience.visionforge.visionManager import kotlin.random.Random fun main() { - val satContext = Global.context("sat") { + val satContext = Global.buildContext ("sat") { plugin(Solids) } diff --git a/gradle.properties b/gradle.properties index 930bba55..d9bddc47 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,9 +1,10 @@ kotlin.code.style=official -kotlin.parallel.tasks.in.project=true + kotlin.mpp.enableGranularSourceSetsMetadata=true -kotlin.native.enableDependencyPropagation=false kotlin.mpp.stability.nowarn=true -org.gradle.jvmargs=-XX:MaxMetaspaceSize=512m -org.gradle.parallel=true -systemProp.org.gradle.internal.publish.checksums.insecure=true \ No newline at end of file +kotlin.native.enableDependencyPropagation=false +kotlin.parallel.tasks.in.project=true + +org.gradle.jvmargs=-XX:MaxMetaspaceSize=1G +org.gradle.parallel=true \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 442d9132..f371643e 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.8.3-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.0-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/jupyter/visionforge-gdml-jupyter/src/jsMain/kotlin/gdmlJupyter.kt b/jupyter/visionforge-gdml-jupyter/src/jsMain/kotlin/gdmlJupyter.kt index 57bdb872..9c4d8140 100644 --- a/jupyter/visionforge-gdml-jupyter/src/jsMain/kotlin/gdmlJupyter.kt +++ b/jupyter/visionforge-gdml-jupyter/src/jsMain/kotlin/gdmlJupyter.kt @@ -1,16 +1,14 @@ package space.kscience.visionforge.gdml.jupyter -import kotlinx.browser.window import kotlinx.css.ListStyleType import kotlinx.css.listStyleType import space.kscience.dataforge.misc.DFExperimental -import space.kscience.visionforge.VisionForge import space.kscience.visionforge.bootstrap.useBootstrap -import space.kscience.visionforge.plugins +import space.kscience.visionforge.runVisionClient import styled.injectGlobal @DFExperimental -fun main(): Unit = VisionForge.run { +fun main(): Unit = runVisionClient { useBootstrap() injectGlobal { rule("ul.nav") { @@ -25,8 +23,5 @@ fun main(): Unit = VisionForge.run { listStyleType = ListStyleType.none } } - console.info("Starting VisionForge context") - plugins.fetch(ThreeWithControls) - window.asDynamic()["VisionForge"] = VisionForge - renderVisionsInWindow() + plugin(ThreeWithControls) } \ No newline at end of file diff --git a/jupyter/visionforge-gdml-jupyter/src/jvmMain/kotlin/GdmlForJupyter.kt b/jupyter/visionforge-gdml-jupyter/src/jvmMain/kotlin/GdmlForJupyter.kt index 0161d621..86041d32 100644 --- a/jupyter/visionforge-gdml-jupyter/src/jvmMain/kotlin/GdmlForJupyter.kt +++ b/jupyter/visionforge-gdml-jupyter/src/jvmMain/kotlin/GdmlForJupyter.kt @@ -9,16 +9,14 @@ import org.jetbrains.kotlinx.jupyter.api.HTML import org.jetbrains.kotlinx.jupyter.api.annotations.JupyterLibrary import org.jetbrains.kotlinx.jupyter.api.libraries.JupyterIntegration import org.jetbrains.kotlinx.jupyter.api.libraries.resources +import space.kscience.dataforge.context.Context import space.kscience.dataforge.misc.DFExperimental import space.kscience.gdml.Gdml import space.kscience.visionforge.Vision -import space.kscience.visionforge.VisionForge import space.kscience.visionforge.gdml.toVision import space.kscience.visionforge.html.HtmlVisionFragment import space.kscience.visionforge.html.Page import space.kscience.visionforge.html.embedVisionFragment -import space.kscience.visionforge.html.fragment -import space.kscience.visionforge.plugins import space.kscience.visionforge.solid.Solids import space.kscience.visionforge.visionManager @@ -26,13 +24,17 @@ import space.kscience.visionforge.visionManager @DFExperimental internal class GdmlForJupyter : JupyterIntegration() { + private val context = Context("GDML") { + plugin(Solids) + } + private var counter = 0 private fun produceHtmlVisionString(fragment: HtmlVisionFragment) = createHTML().div { val id = "visionforge.vision[${counter++}]" div { this.id = id - embedVisionFragment(VisionForge.visionManager, fragment = fragment) + embedVisionFragment(context.visionManager, fragment = fragment) } script { type = "text/javascript" @@ -43,7 +45,7 @@ internal class GdmlForJupyter : JupyterIntegration() { override fun Builder.onLoaded() { resources { - js("three"){ + js("three") { classPath("js/gdml-jupyter.js") } // css("override") { @@ -51,10 +53,6 @@ internal class GdmlForJupyter : JupyterIntegration() { // } } - onLoaded { - VisionForge.plugins.fetch(Solids) - } - import( "space.kscience.gdml.*", "kotlinx.html.*", @@ -64,17 +62,15 @@ internal class GdmlForJupyter : JupyterIntegration() { "space.kscience.visionforge.gdml.jupyter.*" ) - import() - render { gdmlModel -> - val fragment = VisionForge.fragment { + val fragment = HtmlVisionFragment { vision(gdmlModel.toVision()) } HTML(produceHtmlVisionString(fragment)) } render { vision -> - val fragment = VisionForge.fragment { + val fragment = HtmlVisionFragment { vision(vision) } diff --git a/settings.gradle.kts b/settings.gradle.kts index 9654d977..1c923b9a 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1,9 +1,8 @@ pluginManagement { - val kotlinVersion = "1.4.31" - val toolsVersion = "0.9.2" + val kotlinVersion = "1.5.0" + val toolsVersion = "0.9.5" repositories { - mavenLocal() maven("https://repo.kotlin.link") mavenCentral() gradlePluginPortal() @@ -14,11 +13,10 @@ pluginManagement { 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("ru.mipt.npm.gradle.publish") version toolsVersion - kotlin("jvm") version kotlinVersion - kotlin("jupyter.api") version "0.8.3.279" - kotlin("js") version kotlinVersion kotlin("multiplatform") version kotlinVersion + kotlin("jvm") version kotlinVersion + kotlin("js") version kotlinVersion + kotlin("jupyter.api") version "0.9.1-20" } } @@ -47,5 +45,6 @@ include( ":demo:sat-demo", ":demo:playground", ":demo:jupyter-playground", + ":demo:plotly-fx", ":jupyter:visionforge-gdml-jupyter" ) \ No newline at end of file diff --git a/ui/bootstrap/build.gradle.kts b/ui/bootstrap/build.gradle.kts index 50873978..b1b0588e 100644 --- a/ui/bootstrap/build.gradle.kts +++ b/ui/bootstrap/build.gradle.kts @@ -1,4 +1,5 @@ plugins { + kotlin("js") id("ru.mipt.npm.gradle.js") } diff --git a/ui/bootstrap/src/main/kotlin/space/kscience/visionforge/bootstrap/outputConfig.kt b/ui/bootstrap/src/main/kotlin/space/kscience/visionforge/bootstrap/outputConfig.kt index 604eaec1..b65b9666 100644 --- a/ui/bootstrap/src/main/kotlin/space/kscience/visionforge/bootstrap/outputConfig.kt +++ b/ui/bootstrap/src/main/kotlin/space/kscience/visionforge/bootstrap/outputConfig.kt @@ -1,25 +1,25 @@ package space.kscience.visionforge.bootstrap -import kotlinx.css.* +import kotlinx.css.BorderStyle +import kotlinx.css.Color +import kotlinx.css.padding import kotlinx.css.properties.border -import kotlinx.html.InputType -import kotlinx.html.js.onChangeFunction +import kotlinx.css.px import kotlinx.html.js.onClickFunction -import org.w3c.dom.HTMLInputElement import org.w3c.dom.events.Event import org.w3c.files.Blob import org.w3c.files.BlobPropertyBag import react.* import react.dom.button -import react.dom.h3 -import react.dom.input -import react.dom.label +import space.kscience.dataforge.meta.descriptors.defaultMeta +import space.kscience.dataforge.meta.withDefault import space.kscience.visionforge.react.flexColumn import space.kscience.visionforge.react.flexRow +import space.kscience.visionforge.react.propertyEditor import space.kscience.visionforge.solid.SolidGroup +import space.kscience.visionforge.solid.specifications.Canvas3DOptions import space.kscience.visionforge.solid.three.ThreeCanvas import styled.css -import styled.styledDiv private fun saveData(event: Event, fileName: String, mimeType: String = "text/plain", dataBuilder: () -> String) { event.stopPropagation(); @@ -48,7 +48,35 @@ public val CanvasControls: FunctionalComponent = functional arrayOf(props.canvas) ) flexColumn { - h3 { +"Axes" } + flexRow { + css{ + border(1.px, BorderStyle.solid, Color.blue) + padding(4.px) + } + button { + +"Export" + attrs { + onClickFunction = { + val json = (props.canvas.content as? SolidGroup)?.let { group -> + visionManager.encodeToString(group) + } + if (json != null) { + saveData(it, "object.json", "text/json") { + json + } + } + } + } + } + } + propertyEditor( + ownProperties = props.canvas.options, + allProperties = props.canvas.options.withDefault(Canvas3DOptions.descriptor.defaultMeta()), + descriptor = Canvas3DOptions.descriptor, + expanded = false + ) + +/* h3 { +"Axes" } flexRow { css{ border(1.px,BorderStyle.solid, Color.blue) @@ -57,9 +85,9 @@ public val CanvasControls: FunctionalComponent = functional label("checkbox-inline") { input(type = InputType.checkBox) { attrs { - defaultChecked = props.canvas.axes.visible + defaultChecked = props.canvas.options.axes.visible onChangeFunction = { - props.canvas.axes.visible = (it.target as HTMLInputElement).checked + props.canvas.options.axes.visible = (it.target as HTMLInputElement).checked } } } @@ -118,5 +146,6 @@ public val CanvasControls: FunctionalComponent = functional } } } + */ } } \ No newline at end of file diff --git a/ui/react/build.gradle.kts b/ui/react/build.gradle.kts index b430a3d2..86c5068f 100644 --- a/ui/react/build.gradle.kts +++ b/ui/react/build.gradle.kts @@ -2,12 +2,11 @@ plugins { id("ru.mipt.npm.gradle.js") } -val reactVersion by extra("17.0.1") val kotlinWrappersVersion: String by rootProject.extra dependencies{ api(project(":visionforge-solid")) - api("org.jetbrains:kotlin-styled:5.2.1-$kotlinWrappersVersion") - api("org.jetbrains:kotlin-react-dom:$reactVersion-$kotlinWrappersVersion") + api("org.jetbrains:kotlin-styled:5.2.3-$kotlinWrappersVersion") + api("org.jetbrains:kotlin-react-dom:17.0.2-$kotlinWrappersVersion") implementation(project(":visionforge-threejs")) } \ No newline at end of file diff --git a/ui/react/src/main/kotlin/space/kscience/visionforge/react/PropertyEditor.kt b/ui/react/src/main/kotlin/space/kscience/visionforge/react/PropertyEditor.kt index 050378a3..34fcf78b 100644 --- a/ui/react/src/main/kotlin/space/kscience/visionforge/react/PropertyEditor.kt +++ b/ui/react/src/main/kotlin/space/kscience/visionforge/react/PropertyEditor.kt @@ -59,6 +59,11 @@ public external interface PropertyEditorProps : RProps { * Flow names of updated properties */ public var updateFlow: Flow? + + /** + * Initial expanded state + */ + public var expanded: Boolean? } private val PropertyEditorItem: FunctionalComponent = @@ -67,7 +72,7 @@ private val PropertyEditorItem: FunctionalComponent = } private fun RBuilder.propertyEditorItem(props: PropertyEditorProps) { - var expanded: Boolean by useState { true } + var expanded: Boolean by useState { props.expanded ?: true } val descriptorItem: ItemDescriptor? = props.descriptor?.get(props.name) var ownProperty: MetaItem? by useState { props.ownProperties.getItem(props.name) } val actualItem: MetaItem? = props.allProperties?.getItem(props.name) @@ -110,7 +115,7 @@ private fun RBuilder.propertyEditorItem(props: PropertyEditorProps) { if (actualItem is MetaItemNode) { val keys = buildSet { (descriptorItem as? NodeDescriptor)?.items?.filterNot { - it.key.startsWith("@") || it.value.hidden + it.key.startsWith("@") || it.value.hidden }?.forEach { add(NameToken(it.key)) } @@ -232,11 +237,12 @@ public val PropertyEditor: FunctionalComponent = functional public fun RBuilder.propertyEditor( ownProperties: MutableItemProvider, - allProperties: ItemProvider?, + allProperties: ItemProvider? = ownProperties, updateFlow: Flow? = null, descriptor: NodeDescriptor? = null, scope: CoroutineScope? = null, key: Any? = null, + expanded: Boolean? = null ) { child(PropertyEditor) { attrs { @@ -246,6 +252,7 @@ public fun RBuilder.propertyEditor( this.descriptor = descriptor this.key = key?.toString() ?: "" this.scope = scope + this.expanded = expanded } } } diff --git a/visionforge-core/src/commonMain/kotlin/space/kscience/visionforge/StyleSheet.kt b/visionforge-core/src/commonMain/kotlin/space/kscience/visionforge/StyleSheet.kt index cdfe2a07..2e688667 100644 --- a/visionforge-core/src/commonMain/kotlin/space/kscience/visionforge/StyleSheet.kt +++ b/visionforge-core/src/commonMain/kotlin/space/kscience/visionforge/StyleSheet.kt @@ -5,11 +5,13 @@ import space.kscience.dataforge.names.Name import space.kscience.dataforge.names.NameToken import space.kscience.dataforge.names.asName import space.kscience.dataforge.names.plus +import kotlin.jvm.JvmInline /** * A container for styles */ -public inline class StyleSheet(private val owner: VisionGroup) { +@JvmInline +public value class StyleSheet(private val owner: VisionGroup) { private val styleNode get() = owner.ownProperties[STYLESHEET_KEY].node diff --git a/visionforge-core/src/commonMain/kotlin/space/kscience/visionforge/VisionForge.kt b/visionforge-core/src/commonMain/kotlin/space/kscience/visionforge/VisionForge.kt deleted file mode 100644 index 90158f9e..00000000 --- a/visionforge-core/src/commonMain/kotlin/space/kscience/visionforge/VisionForge.kt +++ /dev/null @@ -1,16 +0,0 @@ -package space.kscience.visionforge - -import space.kscience.dataforge.context.Context -import space.kscience.dataforge.context.PluginManager -import space.kscience.dataforge.misc.DFExperimental - -public expect object VisionForge - -@DFExperimental -public expect val VisionForge.context: Context - -@DFExperimental -public val VisionForge.plugins: PluginManager get() = context.plugins - -@DFExperimental -public val VisionForge.visionManager: VisionManager get() = plugins.fetch(VisionManager) \ No newline at end of file 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 65f16961..d45cc906 100644 --- a/visionforge-core/src/commonMain/kotlin/space/kscience/visionforge/VisionManager.kt +++ b/visionforge-core/src/commonMain/kotlin/space/kscience/visionforge/VisionManager.kt @@ -93,6 +93,6 @@ public abstract class VisionPlugin(meta: Meta = Meta.EMPTY) : AbstractPlugin(met } /** - * Fetch a [VisionManager] from this plugin + * Fetch a [VisionManager] from this plugin or create a child plugin with a [VisionManager] */ -public val Context.visionManager: VisionManager get() = plugins.fetch(VisionManager) \ No newline at end of file +public val Context.visionManager: VisionManager get() = fetch(VisionManager) \ No newline at end of file diff --git a/visionforge-core/src/commonMain/kotlin/space/kscience/visionforge/html/HtmlVisionFragment.kt b/visionforge-core/src/commonMain/kotlin/space/kscience/visionforge/html/HtmlVisionFragment.kt index 4597a955..9be18263 100644 --- a/visionforge-core/src/commonMain/kotlin/space/kscience/visionforge/html/HtmlVisionFragment.kt +++ b/visionforge-core/src/commonMain/kotlin/space/kscience/visionforge/html/HtmlVisionFragment.kt @@ -4,7 +4,6 @@ import kotlinx.html.FlowContent import kotlinx.html.TagConsumer import kotlinx.html.stream.createHTML import space.kscience.dataforge.misc.DFExperimental -import space.kscience.visionforge.VisionForge public typealias HtmlFragment = TagConsumer<*>.() -> Unit @@ -21,4 +20,4 @@ public fun FlowContent.fragment(fragment: HtmlFragment) { public typealias HtmlVisionFragment = VisionTagConsumer<*>.() -> Unit @DFExperimental -public fun VisionForge.fragment(content: HtmlVisionFragment): VisionTagConsumer<*>.() -> Unit = content \ No newline at end of file +public fun HtmlVisionFragment(content: VisionTagConsumer<*>.() -> Unit): HtmlVisionFragment = content \ No newline at end of file diff --git a/visionforge-core/src/commonMain/kotlin/space/kscience/visionforge/html/Page.kt b/visionforge-core/src/commonMain/kotlin/space/kscience/visionforge/html/Page.kt index ac1642b8..6e807e92 100644 --- a/visionforge-core/src/commonMain/kotlin/space/kscience/visionforge/html/Page.kt +++ b/visionforge-core/src/commonMain/kotlin/space/kscience/visionforge/html/Page.kt @@ -3,15 +3,13 @@ package space.kscience.visionforge.html import kotlinx.html.* import space.kscience.dataforge.context.Context import space.kscience.dataforge.misc.DFExperimental -import space.kscience.visionforge.VisionForge -import space.kscience.visionforge.context import space.kscience.visionforge.visionManager public data class Page( public val context: Context, public val title: String, public val headers: Map, - public val content: HtmlVisionFragment + public val content: HtmlVisionFragment, ) { public fun render(root: TagConsumer): R = root.apply { head { @@ -31,8 +29,8 @@ public data class Page( @DFExperimental -public fun VisionForge.page( +public fun Context.page( title: String = "VisionForge page", vararg headers: Pair, content: HtmlVisionFragment, -): Page = Page(context, title, mapOf(*headers), content) \ No newline at end of file +): Page = Page(this, title, mapOf(*headers), content) \ No newline at end of file diff --git a/visionforge-core/src/commonMain/kotlin/space/kscience/visionforge/html/VisionTagConsumer.kt b/visionforge-core/src/commonMain/kotlin/space/kscience/visionforge/html/VisionTagConsumer.kt index 1ceaee36..aa8e6fcb 100644 --- a/visionforge-core/src/commonMain/kotlin/space/kscience/visionforge/html/VisionTagConsumer.kt +++ b/visionforge-core/src/commonMain/kotlin/space/kscience/visionforge/html/VisionTagConsumer.kt @@ -79,6 +79,9 @@ public abstract class VisionTagConsumer( return vision(name, vision, output.meta) } + /** + * TODO to be replaced by multi-receiver + */ @OptIn(DFExperimental::class) public inline fun TagConsumer.vision( name: String = DEFAULT_VISION_NAME, diff --git a/visionforge-core/src/commonMain/kotlin/space/kscience/visionforge/schemeDesctiptors.kt b/visionforge-core/src/commonMain/kotlin/space/kscience/visionforge/schemeDesctiptors.kt new file mode 100644 index 00000000..f1a5fb1c --- /dev/null +++ b/visionforge-core/src/commonMain/kotlin/space/kscience/visionforge/schemeDesctiptors.kt @@ -0,0 +1,62 @@ +package space.kscience.visionforge + +import space.kscience.dataforge.meta.Scheme +import space.kscience.dataforge.meta.SchemeSpec +import space.kscience.dataforge.meta.descriptors.NodeDescriptor +import space.kscience.dataforge.meta.descriptors.NodeDescriptorBuilder +import space.kscience.dataforge.meta.descriptors.ValueDescriptor +import space.kscience.dataforge.meta.toConfig +import space.kscience.dataforge.values.ValueType +import kotlin.reflect.KProperty1 +import kotlin.reflect.typeOf + +/** + * TODO to be moved into the core + */ +public inline fun NodeDescriptorBuilder.value( + property: KProperty1, + noinline block: ValueDescriptor.() -> Unit = {}, +) { + when (typeOf()) { + typeOf(), typeOf(), typeOf(), typeOf(), typeOf(), typeOf() -> + value(property.name) { + type(ValueType.NUMBER) + block() + } + typeOf() -> value(property.name) { + type(ValueType.BOOLEAN) + block() + } + typeOf>(), typeOf>(), typeOf>(), typeOf>(), typeOf>(), typeOf>(), + typeOf(), typeOf(), typeOf(), typeOf(), typeOf(), + -> value(property.name) { + type(ValueType.NUMBER) + multiple = true + block() + } + typeOf() -> value(property.name) { + type(ValueType.STRING) + block() + } + typeOf>(), typeOf>() -> value(property.name) { + type(ValueType.STRING) + multiple = true + block() + } + else -> value(property.name, block) + } +} + +public fun NodeDescriptor.copy(block: NodeDescriptorBuilder.() -> Unit = {}): NodeDescriptor { + return NodeDescriptorBuilder(toMeta().toConfig()).apply(block) +} + +public inline fun NodeDescriptorBuilder.scheme( + property: KProperty1, + spec: SchemeSpec, + noinline block: NodeDescriptor.() -> Unit = {}, +) { + spec.descriptor?.let { descriptor -> + item(property.name, descriptor.copy(block)) + } +} \ No newline at end of file diff --git a/visionforge-core/src/commonMain/kotlin/space/kscience/visionforge/visionDescriptor.kt b/visionforge-core/src/commonMain/kotlin/space/kscience/visionforge/visionDescriptor.kt index e058c3c6..c56b495e 100644 --- a/visionforge-core/src/commonMain/kotlin/space/kscience/visionforge/visionDescriptor.kt +++ b/visionforge-core/src/commonMain/kotlin/space/kscience/visionforge/visionDescriptor.kt @@ -1,10 +1,7 @@ package space.kscience.visionforge import space.kscience.dataforge.meta.* -import space.kscience.dataforge.meta.descriptors.ItemDescriptor -import space.kscience.dataforge.meta.descriptors.NodeDescriptor -import space.kscience.dataforge.meta.descriptors.ValueDescriptor -import space.kscience.dataforge.meta.descriptors.attributes +import space.kscience.dataforge.meta.descriptors.* import space.kscience.dataforge.names.Name import space.kscience.dataforge.values.ValueType import space.kscience.dataforge.values.asValue @@ -12,13 +9,19 @@ import space.kscience.dataforge.values.asValue private const val INHERITED_DESCRIPTOR_ATTRIBUTE = "inherited" private const val STYLE_DESCRIPTOR_ATTRIBUTE = "useStyles" -public var ItemDescriptor.inherited: Boolean +public val ItemDescriptor.inherited: Boolean + get() = attributes[INHERITED_DESCRIPTOR_ATTRIBUTE].boolean ?: false + +public var ItemDescriptorBuilder.inherited: Boolean get() = attributes[INHERITED_DESCRIPTOR_ATTRIBUTE].boolean ?: false set(value) = attributes { set(INHERITED_DESCRIPTOR_ATTRIBUTE, value) } -public var ItemDescriptor.usesStyles: Boolean +public val ItemDescriptor.usesStyles: Boolean + get() = attributes[STYLE_DESCRIPTOR_ATTRIBUTE].boolean ?: true + +public var ItemDescriptorBuilder.usesStyles: Boolean get() = attributes[STYLE_DESCRIPTOR_ATTRIBUTE].boolean ?: true set(value) = attributes { set(STYLE_DESCRIPTOR_ATTRIBUTE, value) @@ -32,10 +35,13 @@ public val Vision.describedProperties: Meta } } +public val ValueDescriptor.widget: Meta + get() = attributes["widget"].node ?: Meta.EMPTY + /** * Extension property to access the "widget" key of [ValueDescriptor] */ -public var ValueDescriptor.widget: Meta +public var ValueDescriptorBuilder.widget: Meta get() = attributes["widget"].node ?: Meta.EMPTY set(value) { attributes { @@ -43,10 +49,13 @@ public var ValueDescriptor.widget: Meta } } +public val ValueDescriptor.widgetType: String? + get() = attributes["widget.type"].string + /** * Extension property to access the "widget.type" key of [ValueDescriptor] */ -public var ValueDescriptor.widgetType: String? +public var ValueDescriptorBuilder.widgetType: String? get() = attributes["widget.type"].string set(value) { attributes { @@ -60,15 +69,15 @@ public var ValueDescriptor.widgetType: String? public val ItemDescriptor.hidden: Boolean get() = attributes["widget.hide"].boolean ?: false -public fun ItemDescriptor.hide(): Unit = attributes { +public fun ItemDescriptorBuilder.hide(): Unit = attributes { set("widget.hide", true) } -public inline fun > NodeDescriptor.enum( +public inline fun > NodeDescriptorBuilder.enum( key: Name, default: E?, - crossinline modifier: ValueDescriptor.() -> Unit = {}, + crossinline modifier: ValueDescriptorBuilder.() -> Unit = {}, ): Unit = value(key) { type(ValueType.STRING) default?.let { 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 bbbd6c8b..5f35bd74 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 @@ -46,7 +46,7 @@ class HtmlTagTest { } } - val groupRenderer: HtmlVisionRenderer = { _, group, _ -> + val groupRenderer: HtmlVisionRenderer = { _, _, _ -> p { +"This is group" } } diff --git a/visionforge-core/src/jsMain/kotlin/space/kscience/visionforge/VisionClient.kt b/visionforge-core/src/jsMain/kotlin/space/kscience/visionforge/VisionClient.kt index 85c3c9de..9ca71059 100644 --- a/visionforge-core/src/jsMain/kotlin/space/kscience/visionforge/VisionClient.kt +++ b/visionforge-core/src/jsMain/kotlin/space/kscience/visionforge/VisionClient.kt @@ -2,10 +2,7 @@ package space.kscience.visionforge import kotlinx.browser.document import kotlinx.browser.window -import org.w3c.dom.Element -import org.w3c.dom.WebSocket -import org.w3c.dom.asList -import org.w3c.dom.get +import org.w3c.dom.* import org.w3c.dom.url.URL import space.kscience.dataforge.context.* import space.kscience.dataforge.meta.Meta @@ -66,7 +63,7 @@ public class VisionClient : AbstractPlugin() { /** * Fetch from server and render a vision, described in a given with [VisionTagConsumer.OUTPUT_CLASS] class. */ - public fun renderVisionAt(element: Element) { + public fun renderVisionIn(element: Element) { val name = resolveName(element) ?: error("The element is not a vision output") logger.info { "Found DF output with name $name" } if (!element.classList.contains(VisionTagConsumer.OUTPUT_CLASS)) error("The element $element is not an output element") @@ -173,21 +170,58 @@ public class VisionClient : AbstractPlugin() { } } -/** - * Fetch and render visions for all elements with [VisionTagConsumer.OUTPUT_CLASS] class inside given [element]. - */ -public fun VisionClient.renderAllVisionsAt(element: Element) { - val elements = element.getElementsByClassName(VisionTagConsumer.OUTPUT_CLASS) - console.info("Finished search for outputs. Found ${elements.length} items") - elements.asList().forEach { child -> - renderVisionAt(child) + +private fun whenDocumentLoaded(block: Document.() -> Unit): Unit { + if (document.readyState == DocumentReadyState.COMPLETE) { + block(document) + } else { + document.addEventListener("DOMContentLoaded", { block(document) }) } } +/** + * Fetch and render visions for all elements with [VisionTagConsumer.OUTPUT_CLASS] class inside given [element]. + */ +public fun VisionClient.renderAllVisionsIn(element: Element) { + val elements = element.getElementsByClassName(VisionTagConsumer.OUTPUT_CLASS) + console.info("Finished search for outputs. Found ${elements.length} items") + elements.asList().forEach { child -> + renderVisionIn(child) + } +} + +/** + * Render all visions in an element with a given [id] + */ +public fun VisionClient.renderAllVisionsById(id: String): Unit = whenDocumentLoaded { + val element = getElementById(id) + if (element != null) { + renderAllVisionsIn(element) + } else { + console.warn("Element with id $id not found") + } +} + + /** * Fetch visions from the server for all elements with [VisionTagConsumer.OUTPUT_CLASS] class in the document body */ -public fun VisionClient.renderAllVisions() { - val element = document.body ?: error("Document does not have a body") - renderAllVisionsAt(element) +public fun VisionClient.renderAllVisions(): Unit = whenDocumentLoaded { + val element = body ?: error("Document does not have a body") + renderAllVisionsIn(element) +} + +/** + * Create a vision client context and render all visions on the page. + */ +public fun runVisionClient(contextBuilder: ContextBuilder.() -> Unit) { + console.info("Starting VisionForge context") + val context = Context("VisionForge"){ + contextBuilder() + plugin(VisionClient) + } + val visionClient = context.fetch(VisionClient) + window.asDynamic()["renderAllVisionsById"] = visionClient::renderAllVisionsById + + visionClient.renderAllVisions() } \ No newline at end of file diff --git a/visionforge-core/src/jsMain/kotlin/space/kscience/visionforge/visionForgeJs.kt b/visionforge-core/src/jsMain/kotlin/space/kscience/visionforge/visionForgeJs.kt deleted file mode 100644 index e605b4d1..00000000 --- a/visionforge-core/src/jsMain/kotlin/space/kscience/visionforge/visionForgeJs.kt +++ /dev/null @@ -1,73 +0,0 @@ -package space.kscience.visionforge - -import kotlinx.browser.document -import kotlinx.browser.window -import org.w3c.dom.COMPLETE -import org.w3c.dom.Document -import org.w3c.dom.DocumentReadyState -import space.kscience.dataforge.context.Context -import space.kscience.dataforge.misc.DFExperimental - - -private fun whenDocumentLoaded(block: Document.() -> Unit): Unit { - if(document.readyState == DocumentReadyState.COMPLETE){ - block(document) - } else { - document.addEventListener("DOMContentLoaded", { block(document) }) - } -} - -@JsExport -@DFExperimental -@JsName("VisionForge") -public actual object VisionForge { - /** - * Render all visions in this [window] using current global state of [VisionForge] - */ - public fun renderVisionsInWindow(): Unit = whenDocumentLoaded { - visionClient.renderAllVisions() - } - - /** - * Render all visions in an element with a given [id] - */ - public fun renderVisionsAt(id: String): Unit = whenDocumentLoaded { - val element = getElementById(id) - if (element != null) { - visionClient.renderAllVisionsAt(element) - } else { - console.warn("Element with id $id not found") - } - } -} - -private val visionForgeContext = Context("VisionForge") { - plugin(VisionClient) -} - -@DFExperimental -public actual val VisionForge.context: Context - get() = visionForgeContext - -@DFExperimental -public val VisionForge.visionClient: VisionClient - get() = plugins.fetch(VisionClient) - - -///** -// * Render all visions in this [window] using current global state of [VisionForge] -// */ -//@DFExperimental -//@JsExport -//public fun renderVisionsInWindow(): Unit { -// VisionForge.renderVisionsInWindow() -//} -// -///** -// * Render all visions in an element with a given [id] -// */ -//@DFExperimental -//@JsExport -//public fun renderVisionsAt(id: String): Unit { -// VisionForge.renderVisionsAt(id) -//} \ No newline at end of file diff --git a/visionforge-core/src/jvmMain/kotlin/space/kscience/visionforge/visionForgeJvm.kt b/visionforge-core/src/jvmMain/kotlin/space/kscience/visionforge/visionForgeJvm.kt deleted file mode 100644 index 6d2802b7..00000000 --- a/visionforge-core/src/jvmMain/kotlin/space/kscience/visionforge/visionForgeJvm.kt +++ /dev/null @@ -1,21 +0,0 @@ -package space.kscience.visionforge - -import space.kscience.dataforge.context.Context -import space.kscience.dataforge.context.PluginFactory -import space.kscience.dataforge.misc.DFExperimental - -public actual object VisionForge - -@DFExperimental -private val visionForgeContext = Context("VisionForge") - -@DFExperimental -public actual val VisionForge.context: Context get() = visionForgeContext - -@DFExperimental -public operator fun VisionForge.invoke(vararg modules: PluginFactory, block: VisionForge.() -> Unit): Unit { - modules.forEach { - plugins.fetch(it) - } - run(block) -} \ No newline at end of file diff --git a/visionforge-gdml/build.gradle.kts b/visionforge-gdml/build.gradle.kts index 738b0724..aa40405a 100644 --- a/visionforge-gdml/build.gradle.kts +++ b/visionforge-gdml/build.gradle.kts @@ -1,4 +1,5 @@ plugins { + kotlin("multiplatform") id("ru.mipt.npm.gradle.mpp") } @@ -7,7 +8,7 @@ kotlin { val commonMain by getting { dependencies { api(project(":visionforge-solid")) - api("space.kscience:gdml:0.3.2") + api("space.kscience:gdml:0.4.0") } } } diff --git a/visionforge-gdml/src/commonMain/kotlin/space/kscience/visionforge/gdml/GdmlShowcase.kt b/visionforge-gdml/src/commonMain/kotlin/space/kscience/visionforge/gdml/GdmlShowcase.kt deleted file mode 100644 index 03c403aa..00000000 --- a/visionforge-gdml/src/commonMain/kotlin/space/kscience/visionforge/gdml/GdmlShowcase.kt +++ /dev/null @@ -1,57 +0,0 @@ -package space.kscience.visionforge.gdml - -import space.kscience.gdml.* - -public object GdmlShowcase { - public val cubes: Gdml = Gdml { - val center = define.position("center") - structure { - val air = materials.composite("G4_AIR") {} - val tubeMaterial = materials.composite("tube") {} - val boxMaterial = materials.composite("box") {} - - val segment = solids.tube("segment", 20, 5.0) { - rmin = 17 - deltaphi = 60 - aunit = AUnit.DEG - } - val worldBox = solids.box("largeBox", 200, 200, 200) - val smallBox = solids.box("smallBox", 30, 30, 30) - val segmentVolume = volume("segment", tubeMaterial, segment) {} - val circle = volume("composite", boxMaterial, smallBox) { - for (i in 0 until 6) { - physVolume(segmentVolume) { - name = "segment[$i]" - positionref = center - rotation { - z = 60 * i - unit = AUnit.DEG - } - } - } - } - - world = volume("world", air, worldBox) { - for (i in 0 until 3) { - for (j in 0 until 3) { - for (k in 0 until 3) { - physVolume(circle) { - name = "composite[$i,$j,$k]" - position { - x = (-50 + i * 50) - y = (-50 + j * 50) - z = (-50 + k * 50) - } - rotation { - x = i * 120 - y = j * 120 - z = 120 * k - } - } - } - } - } - } - } - } -} \ No newline at end of file diff --git a/visionforge-gdml/src/commonMain/kotlin/space/kscience/visionforge/gdml/GdmlTransformer.kt b/visionforge-gdml/src/commonMain/kotlin/space/kscience/visionforge/gdml/GdmlTransformer.kt index f9bba939..449bd09d 100644 --- a/visionforge-gdml/src/commonMain/kotlin/space/kscience/visionforge/gdml/GdmlTransformer.kt +++ b/visionforge-gdml/src/commonMain/kotlin/space/kscience/visionforge/gdml/GdmlTransformer.kt @@ -35,13 +35,13 @@ public class GdmlTransformerSettings { PROTOTYPE } - public var lUnit: LUnit = LUnit.CM + public var lUnit: LUnit = LUnit.MM public var aUnit: AUnit = AUnit.RADIAN public var solidAction: (GdmlSolid) -> Action = { Action.PROTOTYPE } public var volumeAction: (GdmlGroup) -> Action = { Action.PROTOTYPE } - public var paint: SolidMaterial.(material: GdmlMaterial) -> Unit = { _-> + public var paint: SolidMaterial.(material: GdmlMaterial) -> Unit = { _ -> color(random.nextInt(16777216)) } } @@ -110,7 +110,7 @@ private class GdmlTransformer(val settings: GdmlTransformerSettings) { val styleName = "materials.${material.name}" obj.useStyle(styleName) { - val vfMaterial = settings.run { SolidMaterial().apply { paint(material)}} + val vfMaterial = settings.run { SolidMaterial().apply { paint(material) } } MATERIAL_KEY put vfMaterial.toMeta() "Gdml.material" put material.name } @@ -151,6 +151,24 @@ private class GdmlTransformer(val settings: GdmlTransformerSettings) { physVolume.resolveScale(root) ) + private fun GdmlSolid.lscale(targetUnit: LUnit): Float { + val solidUnit = lunit ?: return 1f + return if (solidUnit == targetUnit) { + 1f + } else { + solidUnit.value / targetUnit.value + } + } + + private fun GdmlSolid.ascale(targetUnit: AUnit = AUnit.RAD): Float { + val solidUnit = aunit ?: return 1f + return if (solidUnit == targetUnit) { + 1f + } else { + solidUnit.value / targetUnit.value + } + } + fun SolidGroup.addSolid( root: Gdml, solid: GdmlSolid, @@ -158,7 +176,7 @@ private class GdmlTransformer(val settings: GdmlTransformerSettings) { ): Solid { //context.solidAdded(solid) val lScale = solid.lscale(settings.lUnit) - val aScale = solid.ascale() + val aScale = solid.ascale(settings.aUnit) return when (solid) { is GdmlBox -> box(solid.x * lScale, solid.y * lScale, solid.z * lScale, name) is GdmlTube -> tube( @@ -201,7 +219,7 @@ private class GdmlTransformer(val settings: GdmlTransformerSettings) { scaleZ = solid.scale.z.toFloat() } } - is GdmlSphere -> sphereLayer(solid.rmax * lScale, solid.rmin * lScale, name) { + is GdmlSphere -> sphereLayer(solid.rmax * lScale, solid.rmin * lScale, name) { phi = solid.deltaphi * aScale theta = solid.deltatheta * aScale phiStart = solid.startphi * aScale @@ -299,7 +317,7 @@ private class GdmlTransformer(val settings: GdmlTransformerSettings) { when (settings.volumeAction(volume)) { GdmlTransformerSettings.Action.ADD -> { val group: SolidGroup = volume(root, volume) - this[physVolume.name ?: ""] = group.withPosition(root, physVolume) + this[physVolume.name] = group.withPosition(root, physVolume) } GdmlTransformerSettings.Action.PROTOTYPE -> { proxyVolume(root, this, physVolume, volume) @@ -378,7 +396,7 @@ private class GdmlTransformer(val settings: GdmlTransformerSettings) { return final } - fun transform(root: Gdml): SolidGroup = finalize(volume(root, root.world)) + fun transform(root: Gdml): SolidGroup = finalize(volume(root, root.world.resolve(root) ?: error("GDML root is not resolved"))) } diff --git a/visionforge-gdml/src/commonTest/kotlin/TestCubes.kt b/visionforge-gdml/src/commonTest/kotlin/TestCubes.kt index 22f12553..a364996c 100644 --- a/visionforge-gdml/src/commonTest/kotlin/TestCubes.kt +++ b/visionforge-gdml/src/commonTest/kotlin/TestCubes.kt @@ -2,12 +2,8 @@ package space.kscience.visionforge.gdml import space.kscience.dataforge.context.Context import space.kscience.dataforge.names.toName -import space.kscience.gdml.Gdml -import space.kscience.gdml.GdmlBox -import space.kscience.gdml.decodeFromString -import space.kscience.gdml.encodeToString +import space.kscience.gdml.* import space.kscience.visionforge.Vision -import space.kscience.visionforge.gdml.GdmlShowcase.cubes import space.kscience.visionforge.get import space.kscience.visionforge.solid.* import space.kscience.visionforge.visionManager @@ -21,13 +17,16 @@ internal val testContext = Context("TEST") { class TestCubes { + val cubes = GdmlShowCase.cubes() + @Test fun testCubesDirect() { val vision = cubes.toVision() +// println(Solids.encodeToString(vision)) val smallBoxPrototype = vision.getPrototype("solids.smallBox".toName()) as? Box assertNotNull(smallBoxPrototype) assertEquals(30.0, smallBoxPrototype.xSize.toDouble()) - val smallBoxVision = vision["composite[1,1,1].smallBox"]?.prototype as? Box + val smallBoxVision = vision["composite-111.smallBox"]?.prototype as? Box assertNotNull(smallBoxVision) assertEquals(30.0, smallBoxVision.xSize.toDouble()) } diff --git a/visionforge-gdml/src/jvmTest/kotlin/space/kscience/visionforge/gdml/bmanStatistics.kt b/visionforge-gdml/src/jvmTest/kotlin/space/kscience/visionforge/gdml/bmanStatistics.kt index b61a7813..eccac343 100644 --- a/visionforge-gdml/src/jvmTest/kotlin/space/kscience/visionforge/gdml/bmanStatistics.kt +++ b/visionforge-gdml/src/jvmTest/kotlin/space/kscience/visionforge/gdml/bmanStatistics.kt @@ -4,6 +4,7 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext import nl.adaptivity.xmlutil.StAXReader import space.kscience.gdml.Gdml +import space.kscience.gdml.decodeFromReader import space.kscience.visionforge.solid.prototype import space.kscience.visionforge.visitor.countDistinct import space.kscience.visionforge.visitor.flowStatistics @@ -17,7 +18,7 @@ suspend fun main() { File("D:\\Work\\Projects\\dataforge-vis\\visionforge-gdml\\src\\jvmTest\\resources\\gdml\\BM@N.gdml").inputStream() val xmlReader = StAXReader(stream, "UTF-8") - val xml = Gdml.format.decodeFromReader(Gdml.serializer(), xmlReader) + val xml = Gdml.decodeFromReader( xmlReader) val vision = xml.toVision() diff --git a/visionforge-plotly/build.gradle.kts b/visionforge-plotly/build.gradle.kts index 4f8b04db..9844b470 100644 --- a/visionforge-plotly/build.gradle.kts +++ b/visionforge-plotly/build.gradle.kts @@ -4,12 +4,12 @@ plugins { val plotlyVersion = "0.4.0-dev-1" -kscience{ +kscience { useSerialization() } kotlin { - js{ + js { //binaries.library() binaries.executable() browser { @@ -19,15 +19,11 @@ kotlin { } } - afterEvaluate { - val jsBrowserDistribution by tasks.getting + val jsBrowserDistribution by tasks.getting - tasks.getByName("jvmProcessResources") { - dependsOn(jsBrowserDistribution) - afterEvaluate { - from(jsBrowserDistribution) - } - } + tasks.getByName("jvmProcessResources") { + dependsOn(jsBrowserDistribution) + from(jsBrowserDistribution) } sourceSets { diff --git a/visionforge-plotly/src/commonMain/kotlin/space/kscience/visionforge/plotly/PlotlyPlugin.kt b/visionforge-plotly/src/commonMain/kotlin/space/kscience/visionforge/plotly/PlotlyPlugin.kt index 84e3b5d1..da6185c6 100644 --- a/visionforge-plotly/src/commonMain/kotlin/space/kscience/visionforge/plotly/PlotlyPlugin.kt +++ b/visionforge-plotly/src/commonMain/kotlin/space/kscience/visionforge/plotly/PlotlyPlugin.kt @@ -4,26 +4,15 @@ import kotlinx.serialization.modules.SerializersModule import kotlinx.serialization.modules.polymorphic import kotlinx.serialization.modules.subclass import space.kscience.dataforge.context.PluginFactory -import space.kscience.dataforge.misc.DFExperimental import space.kscience.visionforge.Vision -import space.kscience.visionforge.VisionForge import space.kscience.visionforge.VisionPlugin -import space.kscience.visionforge.plugins -public expect class PlotlyPlugin : VisionPlugin{ - public companion object: PluginFactory +public expect class PlotlyPlugin : VisionPlugin { + public companion object : PluginFactory } internal val plotlySerializersModule = SerializersModule { polymorphic(Vision::class) { subclass(VisionOfPlotly.serializer()) } -} - -/** - * Ensure that [PlotlyPlugin] is loaded in the global [VisionForge] context - */ -@DFExperimental -public fun VisionForge.usePlotly() { - plugins.fetch(PlotlyPlugin) } \ No newline at end of file diff --git a/visionforge-plotly/src/jvmMain/kotlin/space/kscience/visionforge/plotly/plotlyHeaders.kt b/visionforge-plotly/src/jvmMain/kotlin/space/kscience/visionforge/plotly/plotlyHeaders.kt index a09909c7..8c986125 100644 --- a/visionforge-plotly/src/jvmMain/kotlin/space/kscience/visionforge/plotly/plotlyHeaders.kt +++ b/visionforge-plotly/src/jvmMain/kotlin/space/kscience/visionforge/plotly/plotlyHeaders.kt @@ -1,30 +1,22 @@ package space.kscience.visionforge.plotly -import kotlinx.html.script -import kotlinx.html.unsafe -import space.kscience.dataforge.misc.DFExperimental -import space.kscience.visionforge.html.HtmlFragment -import space.kscience.visionforge.html.ResourceLocation -import space.kscience.visionforge.html.scriptHeader -import java.nio.file.Path - -internal val plotlyScriptLocation = "js/visionforge-three.js" - -/** - * A header that stores/embeds plotly bundle and registers plotly renderer in the frontend - */ -@OptIn(DFExperimental::class) -public fun plotlyHeader(location: ResourceLocation, filePath: Path? = null): HtmlFragment = { - scriptHeader( - plotlyScriptLocation, - resourceLocation = location, - htmlPath = filePath - ).invoke(this) - script { - type = "text/javascript" - unsafe { - //language=JavaScript - +"space.kscience.visionforge.plotly.loadPlotly()" - } - } -} +//internal val plotlyScriptLocation = "js/visionforge-three.js" +// +///** +// * A header that stores/embeds plotly bundle and registers plotly renderer in the frontend +// */ +//@OptIn(DFExperimental::class) +//public fun plotlyHeader(location: ResourceLocation, filePath: Path? = null): HtmlFragment = { +// scriptHeader( +// plotlyScriptLocation, +// resourceLocation = location, +// htmlPath = filePath +// ).invoke(this) +// script { +// type = "text/javascript" +// unsafe { +// //language=JavaScript +// +"space.kscience.visionforge.plotly.loadPlotly()" +// } +// } +//} diff --git a/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/Solids.kt b/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/Solids.kt index b6d9bb16..fc296244 100644 --- a/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/Solids.kt +++ b/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/Solids.kt @@ -17,9 +17,7 @@ import kotlin.reflect.KClass public class Solids(meta: Meta) : VisionPlugin(meta) { - override val tag: PluginTag get() = Companion.tag - override val visionSerializersModule: SerializersModule get() = serializersModuleForSolids public companion object : PluginFactory { 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 de82d02a..6443bdd0 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 @@ -9,6 +9,9 @@ import kotlin.math.PI import kotlin.math.cos import kotlin.math.sin +/** + * A spherical layer + */ @Serializable @SerialName("solid.sphereLayer") public class SphereLayer( diff --git a/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/specifications/Axes.kt b/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/specifications/Axes.kt index 2f907091..8b59a8b4 100644 --- a/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/specifications/Axes.kt +++ b/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/specifications/Axes.kt @@ -3,7 +3,9 @@ package space.kscience.visionforge.solid.specifications import space.kscience.dataforge.meta.Scheme import space.kscience.dataforge.meta.SchemeSpec import space.kscience.dataforge.meta.boolean +import space.kscience.dataforge.meta.descriptors.NodeDescriptor import space.kscience.dataforge.meta.double +import space.kscience.visionforge.value public class Axes : Scheme() { public var visible: Boolean by boolean(false) @@ -13,5 +15,13 @@ public class Axes : Scheme() { public companion object : SchemeSpec(::Axes) { public const val AXIS_SIZE: Double = 1000.0 public const val AXIS_WIDTH: Double = 3.0 + + override val descriptor: NodeDescriptor by lazy { + NodeDescriptor { + value(Axes::visible) + value(Axes::size) + value(Axes::width) + } + } } } \ No newline at end of file diff --git a/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/specifications/Camera.kt b/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/specifications/Camera.kt index b035e9fe..00c36d50 100644 --- a/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/specifications/Camera.kt +++ b/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/specifications/Camera.kt @@ -2,8 +2,10 @@ package space.kscience.visionforge.solid.specifications import space.kscience.dataforge.meta.Scheme import space.kscience.dataforge.meta.SchemeSpec +import space.kscience.dataforge.meta.descriptors.NodeDescriptor import space.kscience.dataforge.meta.double import space.kscience.dataforge.meta.int +import space.kscience.visionforge.value import kotlin.math.PI public class Camera : Scheme() { @@ -25,5 +27,16 @@ public class Camera : Scheme() { public const val NEAR_CLIP: Double = 0.1 public const val FAR_CLIP: Double = 10000.0 public const val FIELD_OF_VIEW: Int = 75 + + override val descriptor: NodeDescriptor by lazy { + NodeDescriptor { + value(Camera::fov) + value(Camera::nearClip) + value(Camera::farClip) + value(Camera::distance) + value(Camera::azimuth) + value(Camera::zenith) + } + } } } \ No newline at end of file diff --git a/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/specifications/Canvas3DOptions.kt b/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/specifications/Canvas3DOptions.kt index ffb43756..bd3eebc3 100644 --- a/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/specifications/Canvas3DOptions.kt +++ b/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/specifications/Canvas3DOptions.kt @@ -1,7 +1,10 @@ package space.kscience.visionforge.solid.specifications import space.kscience.dataforge.meta.* +import space.kscience.dataforge.meta.descriptors.NodeDescriptor import space.kscience.dataforge.names.Name +import space.kscience.visionforge.scheme +import space.kscience.visionforge.value public class Canvas3DOptions : Scheme() { public var axes: Axes by spec(Axes) @@ -17,14 +20,29 @@ public class Canvas3DOptions : Scheme() { public var maxWith: Number by number { maxSize } public var maxHeight: Number by number { maxSize } - public var onSelect: ((Name?)->Unit)? = null + public var onSelect: ((Name?) -> Unit)? = null - public companion object : SchemeSpec(::Canvas3DOptions) + public companion object : SchemeSpec(::Canvas3DOptions) { + override val descriptor: NodeDescriptor by lazy { + NodeDescriptor { + scheme(Canvas3DOptions::axes, Axes) + scheme(Canvas3DOptions::light, Light) + scheme(Canvas3DOptions::camera, Camera) + scheme(Canvas3DOptions::controls, Controls) + value(Canvas3DOptions::minSize) + value(Canvas3DOptions::minWith) + value(Canvas3DOptions::minHeight) + value(Canvas3DOptions::maxSize) + value(Canvas3DOptions::maxWith) + value(Canvas3DOptions::maxHeight) + } + } + } } public fun Canvas3DOptions.computeWidth(external: Number): Int = (external.toInt()).coerceIn(minWith.toInt()..maxWith.toInt()) public fun Canvas3DOptions.computeHeight(external: Number): Int = - (external.toInt()).coerceIn(minHeight.toInt()..maxHeight.toInt()) \ No newline at end of file + (external.toInt()).coerceIn(minHeight.toInt()..maxHeight.toInt()) diff --git a/visionforge-solid/src/commonTest/kotlin/space/kscience/visionforge/solid/DescriptorTest.kt b/visionforge-solid/src/commonTest/kotlin/space/kscience/visionforge/solid/DescriptorTest.kt new file mode 100644 index 00000000..95f6b23e --- /dev/null +++ b/visionforge-solid/src/commonTest/kotlin/space/kscience/visionforge/solid/DescriptorTest.kt @@ -0,0 +1,22 @@ +package space.kscience.visionforge.solid + +import space.kscience.dataforge.meta.descriptors.ValueDescriptor +import space.kscience.dataforge.meta.descriptors.get +import space.kscience.dataforge.values.ValueType +import space.kscience.visionforge.solid.specifications.Canvas3DOptions +import kotlin.test.Test +import kotlin.test.assertNotNull +import kotlin.test.assertTrue + +class DescriptorTest { + @Test + fun canvasDescriptor() { + val descriptor = Canvas3DOptions.descriptor + //println(descriptor.config) + val axesSize = descriptor["axes.size"] + assertNotNull(axesSize) + assertTrue { + ValueType.NUMBER in (axesSize as ValueDescriptor).type!! + } + } +} \ No newline at end of file diff --git a/visionforge-threejs/build.gradle.kts b/visionforge-threejs/build.gradle.kts index c9f20e92..498c63f8 100644 --- a/visionforge-threejs/build.gradle.kts +++ b/visionforge-threejs/build.gradle.kts @@ -11,5 +11,5 @@ kotlin{ dependencies { api(project(":visionforge-solid")) implementation(npm("three", "0.124.0")) - implementation(npm("three-csg-ts", "2.2.0")) + implementation(npm("three-csg-ts", "2.2.2")) } diff --git a/visionforge-threejs/src/main/kotlin/info/laht/threekt/renderers/WebGLRenderer.kt b/visionforge-threejs/src/main/kotlin/info/laht/threekt/renderers/WebGLRenderer.kt index 80edbbca..aa95f1ba 100644 --- a/visionforge-threejs/src/main/kotlin/info/laht/threekt/renderers/WebGLRenderer.kt +++ b/visionforge-threejs/src/main/kotlin/info/laht/threekt/renderers/WebGLRenderer.kt @@ -28,6 +28,7 @@ package info.laht.threekt.renderers import info.laht.threekt.cameras.Camera +import info.laht.threekt.math.Plane import info.laht.threekt.scenes.Scene import org.w3c.dom.Node @@ -103,4 +104,17 @@ external class WebGLRenderer(params: WebGLRendererParams = definedExternally) { ) fun setPixelRatio(value: Number) + + //clipping + + /** + * User-defined clipping planes specified as THREE.Plane objects in world space. These planes apply globally. + * Points in space whose dot product with the plane is negative are cut away. Default is []. + */ + var clippingPlanes: Array + + /** + * Defines whether the renderer respects object-level clipping planes. Default is false. + */ + var localClippingEnabled: Boolean } diff --git a/visionforge-threejs/src/main/kotlin/space/kscience/visionforge/solid/three/ThreeCanvas.kt b/visionforge-threejs/src/main/kotlin/space/kscience/visionforge/solid/three/ThreeCanvas.kt index b68133b2..c79ee93a 100644 --- a/visionforge-threejs/src/main/kotlin/space/kscience/visionforge/solid/three/ThreeCanvas.kt +++ b/visionforge-threejs/src/main/kotlin/space/kscience/visionforge/solid/three/ThreeCanvas.kt @@ -23,6 +23,7 @@ import space.kscience.dataforge.context.info import space.kscience.dataforge.context.logger import space.kscience.dataforge.meta.get import space.kscience.dataforge.meta.string +import space.kscience.dataforge.meta.useProperty import space.kscience.dataforge.names.Name import space.kscience.dataforge.names.asName import space.kscience.dataforge.names.plus @@ -41,7 +42,7 @@ import kotlin.math.sin public class ThreeCanvas( public val three: ThreePlugin, public val options: Canvas3DOptions, -) { +) { private var root: Object3D? = null private val raycaster = Raycaster() @@ -50,14 +51,23 @@ public class ThreeCanvas( public var content: Solid? = null private set - public var axes: AxesHelper = AxesHelper(options.axes.size.toInt()).apply { visible = options.axes.visible } - private set - - private var light = buildLight(options.light) - private val scene: Scene = Scene().apply { - add(axes) - add(light) + options.useProperty(Canvas3DOptions::axes){axesConfig-> + getObjectByName(AXES_NAME)?.let { remove(it) } + val axesObject = AxesHelper(axes.size.toInt()).apply { visible = axes.visible } + axesObject.name = AXES_NAME + add(axesObject) + } + + //Set up light + options.useProperty(Canvas3DOptions::light){lightConfig-> + //remove old light if present + getObjectByName(LIGHT_NAME)?.let { remove(it) } + //add new light + val lightObject = buildLight(lightConfig) + lightObject.name = LIGHT_NAME + add(lightObject) + } } public var camera: PerspectiveCamera = buildCamera(options.camera) @@ -138,7 +148,7 @@ public class ThreeCanvas( } internal fun attach(element: Element) { - check(element.getElementsByClassName("three-canvas").length == 0){"Three canvas already created in this element"} + check(element.getElementsByClassName("three-canvas").length == 0) { "Three canvas already created in this element" } element.appendChild(canvas) updateSize() } @@ -171,7 +181,7 @@ public class ThreeCanvas( } } - private fun buildLight(spec: Light): info.laht.threekt.lights.Light = AmbientLight(0x404040) + private fun buildLight(spec: Light?): info.laht.threekt.lights.Light = AmbientLight(0x404040) private fun buildCamera(spec: Camera) = PerspectiveCamera( spec.fov, @@ -262,5 +272,7 @@ public class ThreeCanvas( public const val DO_NOT_HIGHLIGHT_TAG: String = "doNotHighlight" private const val HIGHLIGHT_NAME = "@highlight" private const val SELECT_NAME = "@select" + private const val LIGHT_NAME = "@light" + private const val AXES_NAME = "@axes" } } \ No newline at end of file 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 c91698f1..7aa84885 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 @@ -8,11 +8,13 @@ import org.w3c.dom.Element import org.w3c.dom.HTMLElement import space.kscience.dataforge.context.* import space.kscience.dataforge.meta.Meta -import space.kscience.dataforge.misc.DFExperimental import space.kscience.dataforge.names.* -import space.kscience.visionforge.* +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 import kotlin.collections.set import kotlin.reflect.KClass import info.laht.threekt.objects.Group as ThreeGroup @@ -149,14 +151,6 @@ public class ThreePlugin : AbstractPlugin(), ElementVisionRenderer { } } -/** - * Ensure that [ThreePlugin] is loaded in the global [VisionForge] context - */ -@DFExperimental -public fun VisionForge.useThreeJs() { - plugins.fetch(ThreePlugin) -} - public fun ThreePlugin.render( element: HTMLElement, obj: Solid, diff --git a/visionforge-threejs/visionforge-threejs-server/src/jsMain/kotlin/space/kscience/visionforge/three/server/jsMain.kt b/visionforge-threejs/visionforge-threejs-server/src/jsMain/kotlin/space/kscience/visionforge/three/server/jsMain.kt index 48460a92..d6d191f0 100644 --- a/visionforge-threejs/visionforge-threejs-server/src/jsMain/kotlin/space/kscience/visionforge/three/server/jsMain.kt +++ b/visionforge-threejs/visionforge-threejs-server/src/jsMain/kotlin/space/kscience/visionforge/three/server/jsMain.kt @@ -1,14 +1,11 @@ package space.kscience.visionforge.three.server -import kotlinx.browser.window import space.kscience.dataforge.misc.DFExperimental -import space.kscience.visionforge.VisionForge -import space.kscience.visionforge.solid.three.useThreeJs +import space.kscience.visionforge.runVisionClient +import space.kscience.visionforge.solid.three.ThreePlugin + @DFExperimental -public fun main(): Unit = VisionForge.run { - console.info("Starting VisionForge context") - useThreeJs() - window.asDynamic()["VisionForge"] = VisionForge - renderVisionsInWindow() +public fun main(): Unit = runVisionClient { + plugin(ThreePlugin) } \ No newline at end of file diff --git a/visionforge-threejs/visionforge-threejs-server/src/jvmMain/kotlin/space/kscience/visionforge/three/server/serverExtensions.kt b/visionforge-threejs/visionforge-threejs-server/src/jvmMain/kotlin/space/kscience/visionforge/three/server/serverExtensions.kt index 9bd6e6b9..94034547 100644 --- a/visionforge-threejs/visionforge-threejs-server/src/jvmMain/kotlin/space/kscience/visionforge/three/server/serverExtensions.kt +++ b/visionforge-threejs/visionforge-threejs-server/src/jvmMain/kotlin/space/kscience/visionforge/three/server/serverExtensions.kt @@ -1,7 +1,7 @@ package space.kscience.visionforge.three.server +import space.kscience.dataforge.context.Context import space.kscience.dataforge.misc.DFExperimental -import space.kscience.visionforge.VisionForge import space.kscience.visionforge.html.HtmlVisionFragment import space.kscience.visionforge.html.ResourceLocation import space.kscience.visionforge.html.page @@ -16,7 +16,7 @@ public fun VisionServer.useThreeJs(): Unit { } @DFExperimental -public fun VisionForge.makeThreeJsFile( +public fun Context.makeThreeJsFile( content: HtmlVisionFragment, path: Path? = null, title: String = "VisionForge page",