Remove global VisionForge object

This commit is contained in:
Alexander Nozik 2021-05-05 15:28:06 +03:00
parent 97b988d419
commit 0961ae90b7
60 changed files with 573 additions and 476 deletions

View File

@ -1,27 +1,29 @@
plugins { plugins {
id("ru.mipt.npm.gradle.project") id("ru.mipt.npm.gradle.project")
kotlin("multiplatform") apply false
kotlin("jvm") apply false kotlin("jvm") apply false
kotlin("js") apply false kotlin("js") apply false
kotlin("jupyter.api") 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 dataforgeVersion by extra("0.4.0")
val kotlinWrappersVersion by extra("pre.148-kotlin-1.4.30") val kotlinWrappersVersion by extra("pre.152-kotlin-1.4.32")
val fxVersion by extra("14") val fxVersion by extra("11")
allprojects { allprojects {
repositories { repositories {
mavenLocal()
mavenCentral() mavenCentral()
jcenter() jcenter()
maven("https://repo.kotlin.link") maven("https://repo.kotlin.link")
maven("https://kotlin.bintray.com/kotlin-js-wrappers")
maven("https://dl.bintray.com/pdvrieze/maven") 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" group = "space.kscience"
version = "0.2.0-dev-13" version = "0.2.0-dev-15"
} }
subprojects { subprojects {

View File

@ -2,8 +2,7 @@ import ru.mipt.npm.gradle.DependencyConfiguration
import ru.mipt.npm.gradle.FXModule import ru.mipt.npm.gradle.FXModule
plugins { plugins {
kotlin("multiplatform") id("ru.mipt.npm.gradle.mpp")
id("ru.mipt.npm.gradle.common")
application application
} }

View File

@ -3,12 +3,12 @@ package space.kscience.visionforge.gdml
import space.kscience.dataforge.meta.string import space.kscience.dataforge.meta.string
import space.kscience.dataforge.names.toName import space.kscience.dataforge.names.toName
import space.kscience.dataforge.values.asValue 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.setProperty
import space.kscience.visionforge.solid.SolidMaterial import space.kscience.visionforge.solid.SolidMaterial
import kotlin.test.Test import kotlin.test.Test
import kotlin.test.assertEquals import kotlin.test.assertEquals
import kotlin.test.assertTrue import kotlin.test.assertNotNull
class GDMLVisualTest { class GDMLVisualTest {
@ -23,10 +23,10 @@ class GDMLVisualTest {
@Test @Test
fun testPrototypeProperty() { fun testPrototypeProperty() {
val visual = cubes.toVision() val vision = GdmlShowCase.cubes().toVision()
val child = visual["composite[0,0,0].segment[0]".toName()] val child = vision["composite-000.segment-0".toName()]
assertTrue { child!= null } assertNotNull(child)
child?.setProperty(SolidMaterial.MATERIAL_COLOR_KEY, "red".asValue()) child.setProperty(SolidMaterial.MATERIAL_COLOR_KEY, "red".asValue())
assertEquals("red", child?.getProperty(SolidMaterial.MATERIAL_COLOR_KEY).string) assertEquals("red", child.getProperty(SolidMaterial.MATERIAL_COLOR_KEY).string)
} }
} }

View File

@ -4,9 +4,9 @@ import kotlinx.browser.document
import react.child import react.child
import react.dom.render import react.dom.render
import space.kscience.dataforge.context.Global import space.kscience.dataforge.context.Global
import space.kscience.gdml.GdmlShowCase
import space.kscience.visionforge.Application import space.kscience.visionforge.Application
import space.kscience.visionforge.bootstrap.useBootstrap import space.kscience.visionforge.bootstrap.useBootstrap
import space.kscience.visionforge.gdml.GdmlShowcase
import space.kscience.visionforge.gdml.toVision import space.kscience.visionforge.gdml.toVision
import space.kscience.visionforge.solid.three.ThreePlugin import space.kscience.visionforge.solid.three.ThreePlugin
import space.kscience.visionforge.startApplication 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 element = document.getElementById("app") ?: error("Element with id 'app' not found on page")
val context = Global.context("demo") .apply{ val context = Global.buildContext("demo"){
plugins.fetch(ThreePlugin) plugin(ThreePlugin)
} }
render(element) { render(element) {
child(GDMLApp) { child(GDMLApp) {
val vision = GdmlShowcase.cubes.toVision() val vision = GdmlShowCase.cubes().toVision()
//println(context.plugins.fetch(VisionManager).encodeToString(vision)) //println(context.plugins.fetch(VisionManager).encodeToString(vision))
attrs { attrs {
this.context = context this.context = context

View File

@ -3,12 +3,13 @@ package space.kscience.visionforge.gdml.demo
import javafx.geometry.Orientation import javafx.geometry.Orientation
import javafx.scene.Parent import javafx.scene.Parent
import javafx.stage.FileChooser 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.VisionManager
import space.kscience.visionforge.describedProperties import space.kscience.visionforge.describedProperties
import space.kscience.visionforge.editor.VisualObjectEditorFragment import space.kscience.visionforge.editor.VisualObjectEditorFragment
import space.kscience.visionforge.editor.VisualObjectTreeFragment import space.kscience.visionforge.editor.VisualObjectTreeFragment
import space.kscience.visionforge.gdml.GdmlShowcase.cubes
import space.kscience.visionforge.gdml.toVision import space.kscience.visionforge.gdml.toVision
import space.kscience.visionforge.solid.FX3DPlugin import space.kscience.visionforge.solid.FX3DPlugin
import space.kscience.visionforge.solid.FXCanvas3D import space.kscience.visionforge.solid.FXCanvas3D
@ -19,8 +20,13 @@ import tornadofx.*
class GDMLDemoApp : App(GDMLView::class) class GDMLDemoApp : App(GDMLView::class)
class GDMLView : View() { class GDMLView : View() {
private val fx3d = Global.plugins.fetch(FX3DPlugin) private val context = Context {
private val visionManager = Global.plugins.fetch(VisionManager) plugin(FX3DPlugin)
plugin(VisionManager)
}
private val fx3d = context.fetch(FX3DPlugin)
private val visionManager = context.fetch(VisionManager)
private val canvas = FXCanvas3D(fx3d) private val canvas = FXCanvas3D(fx3d)
private val treeFragment = VisualObjectTreeFragment().apply { private val treeFragment = VisualObjectTreeFragment().apply {
@ -61,7 +67,7 @@ class GDMLView : View() {
init { init {
runAsync { runAsync {
cubes.toVision() GdmlShowCase.cubes().toVision()
} ui { } ui {
canvas.render(it) canvas.render(it)
} }

View File

@ -7,9 +7,6 @@ plugins {
repositories { repositories {
mavenCentral() mavenCentral()
maven("https://repo.kotlin.link") 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 { dependencies {

View File

@ -8,19 +8,17 @@ import kotlinx.html.unsafe
import org.jetbrains.kotlinx.jupyter.api.HTML import org.jetbrains.kotlinx.jupyter.api.HTML
import org.jetbrains.kotlinx.jupyter.api.annotations.JupyterLibrary import org.jetbrains.kotlinx.jupyter.api.annotations.JupyterLibrary
import org.jetbrains.kotlinx.jupyter.api.libraries.* import org.jetbrains.kotlinx.jupyter.api.libraries.*
import space.kscience.dataforge.context.Context
import space.kscience.dataforge.misc.DFExperimental import space.kscience.dataforge.misc.DFExperimental
import space.kscience.gdml.Gdml import space.kscience.gdml.Gdml
import space.kscience.plotly.Plot import space.kscience.plotly.Plot
import space.kscience.visionforge.Vision import space.kscience.visionforge.Vision
import space.kscience.visionforge.VisionForge
import space.kscience.visionforge.gdml.toVision import space.kscience.visionforge.gdml.toVision
import space.kscience.visionforge.html.HtmlVisionFragment import space.kscience.visionforge.html.HtmlVisionFragment
import space.kscience.visionforge.html.Page import space.kscience.visionforge.html.Page
import space.kscience.visionforge.html.embedVisionFragment 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.toVision
import space.kscience.visionforge.plotly.usePlotly
import space.kscience.visionforge.plugins
import space.kscience.visionforge.solid.Solids import space.kscience.visionforge.solid.Solids
import space.kscience.visionforge.visionManager import space.kscience.visionforge.visionManager
@ -28,6 +26,11 @@ import space.kscience.visionforge.visionManager
@DFExperimental @DFExperimental
internal class VisionForgePlayGroundForJupyter : JupyterIntegration() { internal class VisionForgePlayGroundForJupyter : JupyterIntegration() {
private val context = Context("VisionForge") {
plugin(Solids)
plugin(PlotlyPlugin)
}
private val jsBundle = ResourceFallbacksBundle(listOf( private val jsBundle = ResourceFallbacksBundle(listOf(
ResourceLocation("js/visionforge-playground.js", ResourcePathType.CLASSPATH_PATH)) ResourceLocation("js/visionforge-playground.js", ResourcePathType.CLASSPATH_PATH))
) )
@ -39,22 +42,17 @@ internal class VisionForgePlayGroundForJupyter : JupyterIntegration() {
val id = "visionforge.vision[${counter++}]" val id = "visionforge.vision[${counter++}]"
div { div {
this.id = id this.id = id
embedVisionFragment(VisionForge.visionManager, fragment = fragment) embedVisionFragment(context.visionManager, fragment = fragment)
} }
script { script {
type = "text/javascript" type = "text/javascript"
unsafe { +"VisionForge.renderVisionsAt(\"$id\");" } unsafe { +"window.renderAllVisionsById(\"$id\");" }
} }
} }
override fun Builder.onLoaded() { override fun Builder.onLoaded() {
resource(jsResource) resource(jsResource)
onLoaded {
VisionForge.plugins.fetch(Solids)
VisionForge.usePlotly()
}
import( import(
"space.kscience.gdml.*", "space.kscience.gdml.*",
"space.kscience.plotly.*", "space.kscience.plotly.*",
@ -65,17 +63,15 @@ internal class VisionForgePlayGroundForJupyter : JupyterIntegration() {
"space.kscience.visionforge.html.page" "space.kscience.visionforge.html.page"
) )
import<VisionForge>()
render<Gdml> { gdmlModel -> render<Gdml> { gdmlModel ->
val fragment = VisionForge.fragment { val fragment = HtmlVisionFragment {
vision(gdmlModel.toVision()) vision(gdmlModel.toVision())
} }
HTML(produceHtmlVisionString(fragment)) HTML(produceHtmlVisionString(fragment))
} }
render<Vision> { vision -> render<Vision> { vision ->
val fragment = VisionForge.fragment { val fragment = HtmlVisionFragment {
vision(vision) vision(vision)
} }
@ -83,7 +79,7 @@ internal class VisionForgePlayGroundForJupyter : JupyterIntegration() {
} }
render<Plot> { plot -> render<Plot> { plot ->
val fragment = VisionForge.fragment { val fragment = HtmlVisionFragment {
vision(plot.toVision()) vision(plot.toVision())
} }

View File

@ -22,6 +22,7 @@ kotlin {
tasks.getByName<ProcessResources>("jvmProcessResources") { tasks.getByName<ProcessResources>("jvmProcessResources") {
dependsOn(jsBrowserDistribution) dependsOn(jsBrowserDistribution)
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
afterEvaluate { afterEvaluate {
from(jsBrowserDistribution) from(jsBrowserDistribution)
} }
@ -57,6 +58,12 @@ application {
mainClass.set("ru.mipt.npm.muon.monitor.server.MMServerKt") mainClass.set("ru.mipt.npm.muon.monitor.server.MMServerKt")
} }
tasks.withType<org.jetbrains.kotlin.gradle.dsl.KotlinJsCompile>(){
kotlinOptions{
freeCompilerArgs = freeCompilerArgs + "-Xir-property-lazy-initialization"
}
}
//distributions { //distributions {
// main { // main {
// contents { // contents {

View File

@ -26,7 +26,7 @@ private class MMDemoApp : Application {
val element = document.getElementById("app") ?: error("Element with id 'app' not found on page") 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) { render(element) {
child(MMApp) { child(MMApp) {
attrs { attrs {

View File

@ -26,6 +26,7 @@ import ru.mipt.npm.muon.monitor.sim.Cos2TrackGenerator
import ru.mipt.npm.muon.monitor.sim.simulateOne import ru.mipt.npm.muon.monitor.sim.simulateOne
import space.kscience.dataforge.context.Context import space.kscience.dataforge.context.Context
import space.kscience.dataforge.context.Global import space.kscience.dataforge.context.Global
import space.kscience.dataforge.context.fetch
import space.kscience.dataforge.misc.DFExperimental import space.kscience.dataforge.misc.DFExperimental
import space.kscience.visionforge.solid.Solids import space.kscience.visionforge.solid.Solids
import java.awt.Desktop import java.awt.Desktop
@ -38,7 +39,7 @@ private val generator = Cos2TrackGenerator(JDKRandomGenerator(223))
fun Application.module(context: Context = Global) { fun Application.module(context: Context = Global) {
val currentDir = File(".").absoluteFile val currentDir = File(".").absoluteFile
environment.log.info("Current directory: $currentDir") environment.log.info("Current directory: $currentDir")
val solidManager = context.plugins.load(Solids) val solidManager = context.fetch(Solids)
install(DefaultHeaders) install(DefaultHeaders)
install(CallLogging) install(CallLogging)

View File

@ -1,14 +1,10 @@
import kotlinx.browser.window
import space.kscience.dataforge.misc.DFExperimental import space.kscience.dataforge.misc.DFExperimental
import space.kscience.visionforge.VisionForge import space.kscience.visionforge.plotly.PlotlyPlugin
import space.kscience.visionforge.plotly.usePlotly import space.kscience.visionforge.runVisionClient
import space.kscience.visionforge.solid.three.useThreeJs import space.kscience.visionforge.solid.three.ThreePlugin
@DFExperimental @DFExperimental
fun main(): Unit = VisionForge.run{ fun main() = runVisionClient {
console.info("Starting VisionForge context") plugin(PlotlyPlugin)
usePlotly() plugin(ThreePlugin)
useThreeJs()
window.asDynamic()["VisionForge"] = VisionForge
renderVisionsInWindow()
} }

View File

@ -1,20 +1,19 @@
package space.kscience.visionforge.examples package space.kscience.visionforge.examples
import space.kscience.dataforge.misc.DFExperimental import space.kscience.dataforge.context.Context
import space.kscience.visionforge.VisionForge import space.kscience.gdml.GdmlShowCase
import space.kscience.visionforge.gdml.GdmlShowcase.cubes
import space.kscience.visionforge.gdml.toVision import space.kscience.visionforge.gdml.toVision
import space.kscience.visionforge.html.ResourceLocation 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.Solids
@DFExperimental fun main() {
fun main() = VisionForge(Solids) { val context = Context {
val content = VisionForge.fragment { plugin(Solids)
}
context.makeVisionFile(resourceLocation = ResourceLocation.SYSTEM){
vision("canvas") { vision("canvas") {
cubes.toVision() GdmlShowCase.cubes().toVision()
} }
} }
makeVisionFile(content, resourceLocation = ResourceLocation.SYSTEM)
} }

View File

@ -1,24 +1,22 @@
package space.kscience.visionforge.examples 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.Gdml
import space.kscience.gdml.LUnit import space.kscience.gdml.LUnit
import space.kscience.gdml.decodeFromStream import space.kscience.gdml.decodeFromStream
import space.kscience.visionforge.VisionForge
import space.kscience.visionforge.gdml.toVision import space.kscience.visionforge.gdml.toVision
import space.kscience.visionforge.html.ResourceLocation 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.Solids
@DFExperimental fun main() {
fun main() = VisionForge(Solids) { val context = Context {
val content = VisionForge.fragment { plugin(Solids)
}
context.makeVisionFile(resourceLocation = ResourceLocation.EMBED) {
vision("canvas") { vision("canvas") {
Gdml.decodeFromStream(Gdml.javaClass.getResourceAsStream("/gdml/babyIAXO.gdml")!!, true).toVision { Gdml.decodeFromStream(javaClass.getResourceAsStream("/gdml/babyIAXO.gdml")!!, true).toVision {
lUnit = LUnit.MM lUnit = LUnit.MM
} }
} }
} }
makeVisionFile(content, resourceLocation = ResourceLocation.EMBED)
} }

View File

@ -1,17 +1,16 @@
package space.kscience.visionforge.examples 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.plotly.scatter
import space.kscience.visionforge.VisionForge
import space.kscience.visionforge.html.ResourceLocation 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.PlotlyPlugin
import space.kscience.visionforge.plotly.plotly import space.kscience.visionforge.plotly.plotly
@DFExperimental fun main() {
fun main() = VisionForge(PlotlyPlugin) { val context = Context {
val fragment = fragment { plugin(PlotlyPlugin)
}
context.makeVisionFile(resourceLocation = ResourceLocation.SYSTEM){
vision { vision {
plotly { plotly {
scatter { scatter {
@ -21,5 +20,4 @@ fun main() = VisionForge(PlotlyPlugin) {
} }
} }
} }
makeVisionFile(fragment, resourceLocation = ResourceLocation.SYSTEM)
} }

View File

@ -1,20 +1,23 @@
package space.kscience.visionforge.examples package space.kscience.visionforge.examples
import kotlinx.html.h1 import kotlinx.html.h1
import space.kscience.dataforge.misc.DFExperimental import space.kscience.dataforge.context.Context
import space.kscience.visionforge.VisionForge
import space.kscience.visionforge.html.ResourceLocation import space.kscience.visionforge.html.ResourceLocation
import space.kscience.visionforge.html.fragment
import space.kscience.visionforge.invoke
import space.kscience.visionforge.solid.* import space.kscience.visionforge.solid.*
import java.nio.file.Paths import java.nio.file.Paths
import kotlin.random.Random import kotlin.random.Random
@OptIn(DFExperimental::class) fun main() {
fun main() = VisionForge(Solids) { val context = Context {
plugin(Solids)
}
val random = Random(112233) val random = Random(112233)
val fragment = fragment {
context.makeVisionFile(
Paths.get("randomSpheres.html"),
resourceLocation = ResourceLocation.EMBED
) {
h1 { +"Happy new year!" } h1 { +"Happy new year!" }
vision { vision {
solid { solid {
@ -33,9 +36,4 @@ fun main() = VisionForge(Solids) {
} }
} }
} }
makeVisionFile(
fragment,
Paths.get("randomSpheres.html"),
resourceLocation = ResourceLocation.EMBED
)
} }

View File

@ -1,10 +1,9 @@
package space.kscience.visionforge.examples package space.kscience.visionforge.examples
import space.kscience.dataforge.context.Context
import space.kscience.dataforge.misc.DFExperimental 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.ResourceLocation
import space.kscience.visionforge.html.VisionTagConsumer
import space.kscience.visionforge.html.page import space.kscience.visionforge.html.page
import space.kscience.visionforge.html.scriptHeader import space.kscience.visionforge.html.scriptHeader
import space.kscience.visionforge.makeFile import space.kscience.visionforge.makeFile
@ -18,25 +17,26 @@ public fun VisionServer.usePlayground(): Unit {
useScript("js/visionforge-playground.js") useScript("js/visionforge-playground.js")
} }
@DFExperimental @OptIn(DFExperimental::class)
public fun VisionForge.makeVisionFile( public fun Context.makeVisionFile(
content: HtmlVisionFragment,
path: Path? = null, path: Path? = null,
title: String = "VisionForge page", title: String = "VisionForge page",
resourceLocation: ResourceLocation = ResourceLocation.SYSTEM, resourceLocation: ResourceLocation = ResourceLocation.SYSTEM,
show: Boolean = true, show: Boolean = true,
content: VisionTagConsumer<*>.() -> Unit
): Unit { ): Unit {
val actualPath = page(title, content = content).makeFile(path) { actualPath -> val actualPath = page(title, content = content).makeFile(path) { actualPath ->
mapOf("threeJs" to scriptHeader("js/visionforge-playground.js", resourceLocation, actualPath)) mapOf("threeJs" to scriptHeader("js/visionforge-playground.js", resourceLocation, actualPath))
} }
if (show) Desktop.getDesktop().browse(actualPath.toFile().toURI()) if (show) Desktop.getDesktop().browse(actualPath.toFile().toURI())
} }
@DFExperimental //@DFExperimental
public fun VisionForge.makeVisionFile( //public fun Context.makeVisionFile(
vision: Vision, // vision: Vision,
path: Path? = null, // path: Path? = null,
title: String = "VisionForge page", // title: String = "VisionForge page",
resourceLocation: ResourceLocation = ResourceLocation.SYSTEM, // resourceLocation: ResourceLocation = ResourceLocation.SYSTEM,
show: Boolean = true, // show: Boolean = true,
): Unit = makeVisionFile({ vision(vision) }, path, title, resourceLocation, show) //): Unit = makeVisionFile({ vision(vision) }, path, title, resourceLocation, show)

View File

@ -1,22 +1,21 @@
package space.kscience.visionforge.examples package space.kscience.visionforge.examples
import space.kscience.dataforge.misc.DFExperimental import space.kscience.dataforge.context.Context
import space.kscience.visionforge.VisionForge
import space.kscience.visionforge.html.ResourceLocation 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.Solids
import space.kscience.visionforge.solid.box import space.kscience.visionforge.solid.box
import space.kscience.visionforge.solid.solid import space.kscience.visionforge.solid.solid
@DFExperimental fun main() {
fun main() = VisionForge(Solids) { val context = Context {
val content = fragment { plugin(Solids)
}
context.makeVisionFile(resourceLocation = ResourceLocation.SYSTEM){
vision("canvas") { vision("canvas") {
solid { solid {
box(100, 100, 100) box(100, 100, 100)
} }
} }
} }
makeVisionFile(content, resourceLocation = ResourceLocation.SYSTEM)
} }

View File

@ -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"
//}

View File

@ -15,7 +15,7 @@ import space.kscience.visionforge.visionManager
import kotlin.random.Random import kotlin.random.Random
fun main() { fun main() {
val satContext = Global.context("sat") { val satContext = Global.buildContext ("sat") {
plugin(Solids) plugin(Solids)
} }

View File

@ -1,9 +1,10 @@
kotlin.code.style=official kotlin.code.style=official
kotlin.parallel.tasks.in.project=true
kotlin.mpp.enableGranularSourceSetsMetadata=true kotlin.mpp.enableGranularSourceSetsMetadata=true
kotlin.native.enableDependencyPropagation=false
kotlin.mpp.stability.nowarn=true kotlin.mpp.stability.nowarn=true
org.gradle.jvmargs=-XX:MaxMetaspaceSize=512m kotlin.native.enableDependencyPropagation=false
kotlin.parallel.tasks.in.project=true
org.gradle.jvmargs=-XX:MaxMetaspaceSize=1G
org.gradle.parallel=true org.gradle.parallel=true
systemProp.org.gradle.internal.publish.checksums.insecure=true

View File

@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists 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 zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists

View File

@ -1,16 +1,14 @@
package space.kscience.visionforge.gdml.jupyter package space.kscience.visionforge.gdml.jupyter
import kotlinx.browser.window
import kotlinx.css.ListStyleType import kotlinx.css.ListStyleType
import kotlinx.css.listStyleType import kotlinx.css.listStyleType
import space.kscience.dataforge.misc.DFExperimental import space.kscience.dataforge.misc.DFExperimental
import space.kscience.visionforge.VisionForge
import space.kscience.visionforge.bootstrap.useBootstrap import space.kscience.visionforge.bootstrap.useBootstrap
import space.kscience.visionforge.plugins import space.kscience.visionforge.runVisionClient
import styled.injectGlobal import styled.injectGlobal
@DFExperimental @DFExperimental
fun main(): Unit = VisionForge.run { fun main(): Unit = runVisionClient {
useBootstrap() useBootstrap()
injectGlobal { injectGlobal {
rule("ul.nav") { rule("ul.nav") {
@ -25,8 +23,5 @@ fun main(): Unit = VisionForge.run {
listStyleType = ListStyleType.none listStyleType = ListStyleType.none
} }
} }
console.info("Starting VisionForge context") plugin(ThreeWithControls)
plugins.fetch(ThreeWithControls)
window.asDynamic()["VisionForge"] = VisionForge
renderVisionsInWindow()
} }

View File

@ -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.annotations.JupyterLibrary
import org.jetbrains.kotlinx.jupyter.api.libraries.JupyterIntegration import org.jetbrains.kotlinx.jupyter.api.libraries.JupyterIntegration
import org.jetbrains.kotlinx.jupyter.api.libraries.resources import org.jetbrains.kotlinx.jupyter.api.libraries.resources
import space.kscience.dataforge.context.Context
import space.kscience.dataforge.misc.DFExperimental import space.kscience.dataforge.misc.DFExperimental
import space.kscience.gdml.Gdml import space.kscience.gdml.Gdml
import space.kscience.visionforge.Vision import space.kscience.visionforge.Vision
import space.kscience.visionforge.VisionForge
import space.kscience.visionforge.gdml.toVision import space.kscience.visionforge.gdml.toVision
import space.kscience.visionforge.html.HtmlVisionFragment import space.kscience.visionforge.html.HtmlVisionFragment
import space.kscience.visionforge.html.Page import space.kscience.visionforge.html.Page
import space.kscience.visionforge.html.embedVisionFragment 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.solid.Solids
import space.kscience.visionforge.visionManager import space.kscience.visionforge.visionManager
@ -26,13 +24,17 @@ import space.kscience.visionforge.visionManager
@DFExperimental @DFExperimental
internal class GdmlForJupyter : JupyterIntegration() { internal class GdmlForJupyter : JupyterIntegration() {
private val context = Context("GDML") {
plugin(Solids)
}
private var counter = 0 private var counter = 0
private fun produceHtmlVisionString(fragment: HtmlVisionFragment) = createHTML().div { private fun produceHtmlVisionString(fragment: HtmlVisionFragment) = createHTML().div {
val id = "visionforge.vision[${counter++}]" val id = "visionforge.vision[${counter++}]"
div { div {
this.id = id this.id = id
embedVisionFragment(VisionForge.visionManager, fragment = fragment) embedVisionFragment(context.visionManager, fragment = fragment)
} }
script { script {
type = "text/javascript" type = "text/javascript"
@ -43,7 +45,7 @@ internal class GdmlForJupyter : JupyterIntegration() {
override fun Builder.onLoaded() { override fun Builder.onLoaded() {
resources { resources {
js("three"){ js("three") {
classPath("js/gdml-jupyter.js") classPath("js/gdml-jupyter.js")
} }
// css("override") { // css("override") {
@ -51,10 +53,6 @@ internal class GdmlForJupyter : JupyterIntegration() {
// } // }
} }
onLoaded {
VisionForge.plugins.fetch(Solids)
}
import( import(
"space.kscience.gdml.*", "space.kscience.gdml.*",
"kotlinx.html.*", "kotlinx.html.*",
@ -64,17 +62,15 @@ internal class GdmlForJupyter : JupyterIntegration() {
"space.kscience.visionforge.gdml.jupyter.*" "space.kscience.visionforge.gdml.jupyter.*"
) )
import<VisionForge>()
render<Gdml> { gdmlModel -> render<Gdml> { gdmlModel ->
val fragment = VisionForge.fragment { val fragment = HtmlVisionFragment {
vision(gdmlModel.toVision()) vision(gdmlModel.toVision())
} }
HTML(produceHtmlVisionString(fragment)) HTML(produceHtmlVisionString(fragment))
} }
render<Vision> { vision -> render<Vision> { vision ->
val fragment = VisionForge.fragment { val fragment = HtmlVisionFragment {
vision(vision) vision(vision)
} }

View File

@ -1,9 +1,8 @@
pluginManagement { pluginManagement {
val kotlinVersion = "1.4.31" val kotlinVersion = "1.5.0"
val toolsVersion = "0.9.2" val toolsVersion = "0.9.5"
repositories { repositories {
mavenLocal()
maven("https://repo.kotlin.link") maven("https://repo.kotlin.link")
mavenCentral() mavenCentral()
gradlePluginPortal() gradlePluginPortal()
@ -14,11 +13,10 @@ pluginManagement {
id("ru.mipt.npm.gradle.mpp") version toolsVersion id("ru.mipt.npm.gradle.mpp") version toolsVersion
id("ru.mipt.npm.gradle.jvm") version toolsVersion id("ru.mipt.npm.gradle.jvm") version toolsVersion
id("ru.mipt.npm.gradle.js") 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("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:sat-demo",
":demo:playground", ":demo:playground",
":demo:jupyter-playground", ":demo:jupyter-playground",
":demo:plotly-fx",
":jupyter:visionforge-gdml-jupyter" ":jupyter:visionforge-gdml-jupyter"
) )

View File

@ -1,4 +1,5 @@
plugins { plugins {
kotlin("js")
id("ru.mipt.npm.gradle.js") id("ru.mipt.npm.gradle.js")
} }

View File

@ -1,25 +1,25 @@
package space.kscience.visionforge.bootstrap 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.css.properties.border
import kotlinx.html.InputType import kotlinx.css.px
import kotlinx.html.js.onChangeFunction
import kotlinx.html.js.onClickFunction import kotlinx.html.js.onClickFunction
import org.w3c.dom.HTMLInputElement
import org.w3c.dom.events.Event import org.w3c.dom.events.Event
import org.w3c.files.Blob import org.w3c.files.Blob
import org.w3c.files.BlobPropertyBag import org.w3c.files.BlobPropertyBag
import react.* import react.*
import react.dom.button import react.dom.button
import react.dom.h3 import space.kscience.dataforge.meta.descriptors.defaultMeta
import react.dom.input import space.kscience.dataforge.meta.withDefault
import react.dom.label
import space.kscience.visionforge.react.flexColumn import space.kscience.visionforge.react.flexColumn
import space.kscience.visionforge.react.flexRow import space.kscience.visionforge.react.flexRow
import space.kscience.visionforge.react.propertyEditor
import space.kscience.visionforge.solid.SolidGroup import space.kscience.visionforge.solid.SolidGroup
import space.kscience.visionforge.solid.specifications.Canvas3DOptions
import space.kscience.visionforge.solid.three.ThreeCanvas import space.kscience.visionforge.solid.three.ThreeCanvas
import styled.css import styled.css
import styled.styledDiv
private fun saveData(event: Event, fileName: String, mimeType: String = "text/plain", dataBuilder: () -> String) { private fun saveData(event: Event, fileName: String, mimeType: String = "text/plain", dataBuilder: () -> String) {
event.stopPropagation(); event.stopPropagation();
@ -48,7 +48,35 @@ public val CanvasControls: FunctionalComponent<CanvasControlsProps> = functional
arrayOf(props.canvas) arrayOf(props.canvas)
) )
flexColumn { 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 { flexRow {
css{ css{
border(1.px,BorderStyle.solid, Color.blue) border(1.px,BorderStyle.solid, Color.blue)
@ -57,9 +85,9 @@ public val CanvasControls: FunctionalComponent<CanvasControlsProps> = functional
label("checkbox-inline") { label("checkbox-inline") {
input(type = InputType.checkBox) { input(type = InputType.checkBox) {
attrs { attrs {
defaultChecked = props.canvas.axes.visible defaultChecked = props.canvas.options.axes.visible
onChangeFunction = { 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<CanvasControlsProps> = functional
} }
} }
} }
*/
} }
} }

View File

@ -2,12 +2,11 @@ plugins {
id("ru.mipt.npm.gradle.js") id("ru.mipt.npm.gradle.js")
} }
val reactVersion by extra("17.0.1")
val kotlinWrappersVersion: String by rootProject.extra val kotlinWrappersVersion: String by rootProject.extra
dependencies{ dependencies{
api(project(":visionforge-solid")) api(project(":visionforge-solid"))
api("org.jetbrains:kotlin-styled:5.2.1-$kotlinWrappersVersion") api("org.jetbrains:kotlin-styled:5.2.3-$kotlinWrappersVersion")
api("org.jetbrains:kotlin-react-dom:$reactVersion-$kotlinWrappersVersion") api("org.jetbrains:kotlin-react-dom:17.0.2-$kotlinWrappersVersion")
implementation(project(":visionforge-threejs")) implementation(project(":visionforge-threejs"))
} }

View File

@ -59,6 +59,11 @@ public external interface PropertyEditorProps : RProps {
* Flow names of updated properties * Flow names of updated properties
*/ */
public var updateFlow: Flow<Name>? public var updateFlow: Flow<Name>?
/**
* Initial expanded state
*/
public var expanded: Boolean?
} }
private val PropertyEditorItem: FunctionalComponent<PropertyEditorProps> = private val PropertyEditorItem: FunctionalComponent<PropertyEditorProps> =
@ -67,7 +72,7 @@ private val PropertyEditorItem: FunctionalComponent<PropertyEditorProps> =
} }
private fun RBuilder.propertyEditorItem(props: PropertyEditorProps) { 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) val descriptorItem: ItemDescriptor? = props.descriptor?.get(props.name)
var ownProperty: MetaItem? by useState { props.ownProperties.getItem(props.name) } var ownProperty: MetaItem? by useState { props.ownProperties.getItem(props.name) }
val actualItem: MetaItem? = props.allProperties?.getItem(props.name) val actualItem: MetaItem? = props.allProperties?.getItem(props.name)
@ -232,11 +237,12 @@ public val PropertyEditor: FunctionalComponent<PropertyEditorProps> = functional
public fun RBuilder.propertyEditor( public fun RBuilder.propertyEditor(
ownProperties: MutableItemProvider, ownProperties: MutableItemProvider,
allProperties: ItemProvider?, allProperties: ItemProvider? = ownProperties,
updateFlow: Flow<Name>? = null, updateFlow: Flow<Name>? = null,
descriptor: NodeDescriptor? = null, descriptor: NodeDescriptor? = null,
scope: CoroutineScope? = null, scope: CoroutineScope? = null,
key: Any? = null, key: Any? = null,
expanded: Boolean? = null
) { ) {
child(PropertyEditor) { child(PropertyEditor) {
attrs { attrs {
@ -246,6 +252,7 @@ public fun RBuilder.propertyEditor(
this.descriptor = descriptor this.descriptor = descriptor
this.key = key?.toString() ?: "" this.key = key?.toString() ?: ""
this.scope = scope this.scope = scope
this.expanded = expanded
} }
} }
} }

View File

@ -5,11 +5,13 @@ import space.kscience.dataforge.names.Name
import space.kscience.dataforge.names.NameToken import space.kscience.dataforge.names.NameToken
import space.kscience.dataforge.names.asName import space.kscience.dataforge.names.asName
import space.kscience.dataforge.names.plus import space.kscience.dataforge.names.plus
import kotlin.jvm.JvmInline
/** /**
* A container for styles * 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 private val styleNode get() = owner.ownProperties[STYLESHEET_KEY].node

View File

@ -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)

View File

@ -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) public val Context.visionManager: VisionManager get() = fetch(VisionManager)

View File

@ -4,7 +4,6 @@ import kotlinx.html.FlowContent
import kotlinx.html.TagConsumer import kotlinx.html.TagConsumer
import kotlinx.html.stream.createHTML import kotlinx.html.stream.createHTML
import space.kscience.dataforge.misc.DFExperimental import space.kscience.dataforge.misc.DFExperimental
import space.kscience.visionforge.VisionForge
public typealias HtmlFragment = TagConsumer<*>.() -> Unit public typealias HtmlFragment = TagConsumer<*>.() -> Unit
@ -21,4 +20,4 @@ public fun FlowContent.fragment(fragment: HtmlFragment) {
public typealias HtmlVisionFragment = VisionTagConsumer<*>.() -> Unit public typealias HtmlVisionFragment = VisionTagConsumer<*>.() -> Unit
@DFExperimental @DFExperimental
public fun VisionForge.fragment(content: HtmlVisionFragment): VisionTagConsumer<*>.() -> Unit = content public fun HtmlVisionFragment(content: VisionTagConsumer<*>.() -> Unit): HtmlVisionFragment = content

View File

@ -3,15 +3,13 @@ package space.kscience.visionforge.html
import kotlinx.html.* import kotlinx.html.*
import space.kscience.dataforge.context.Context import space.kscience.dataforge.context.Context
import space.kscience.dataforge.misc.DFExperimental import space.kscience.dataforge.misc.DFExperimental
import space.kscience.visionforge.VisionForge
import space.kscience.visionforge.context
import space.kscience.visionforge.visionManager import space.kscience.visionforge.visionManager
public data class Page( public data class Page(
public val context: Context, public val context: Context,
public val title: String, public val title: String,
public val headers: Map<String, HtmlFragment>, public val headers: Map<String, HtmlFragment>,
public val content: HtmlVisionFragment public val content: HtmlVisionFragment,
) { ) {
public fun <R> render(root: TagConsumer<R>): R = root.apply { public fun <R> render(root: TagConsumer<R>): R = root.apply {
head { head {
@ -31,8 +29,8 @@ public data class Page(
@DFExperimental @DFExperimental
public fun VisionForge.page( public fun Context.page(
title: String = "VisionForge page", title: String = "VisionForge page",
vararg headers: Pair<String, HtmlFragment>, vararg headers: Pair<String, HtmlFragment>,
content: HtmlVisionFragment, content: HtmlVisionFragment,
): Page = Page(context, title, mapOf(*headers), content) ): Page = Page(this, title, mapOf(*headers), content)

View File

@ -79,6 +79,9 @@ public abstract class VisionTagConsumer<R>(
return vision(name, vision, output.meta) return vision(name, vision, output.meta)
} }
/**
* TODO to be replaced by multi-receiver
*/
@OptIn(DFExperimental::class) @OptIn(DFExperimental::class)
public inline fun <T> TagConsumer<T>.vision( public inline fun <T> TagConsumer<T>.vision(
name: String = DEFAULT_VISION_NAME, name: String = DEFAULT_VISION_NAME,

View File

@ -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 <S : Scheme, reified T> NodeDescriptorBuilder.value(
property: KProperty1<S, T>,
noinline block: ValueDescriptor.() -> Unit = {},
) {
when (typeOf<T>()) {
typeOf<Number>(), typeOf<Int>(), typeOf<Double>(), typeOf<Short>(), typeOf<Long>(), typeOf<Float>() ->
value(property.name) {
type(ValueType.NUMBER)
block()
}
typeOf<Boolean>() -> value(property.name) {
type(ValueType.BOOLEAN)
block()
}
typeOf<List<Number>>(), typeOf<List<Int>>(), typeOf<List<Double>>(), typeOf<List<Short>>(), typeOf<List<Long>>(), typeOf<List<Float>>(),
typeOf<IntArray>(), typeOf<DoubleArray>(), typeOf<ShortArray>(), typeOf<LongArray>(), typeOf<FloatArray>(),
-> value(property.name) {
type(ValueType.NUMBER)
multiple = true
block()
}
typeOf<String>() -> value(property.name) {
type(ValueType.STRING)
block()
}
typeOf<List<String>>(), typeOf<Array<String>>() -> 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 <S : Scheme, reified T : Scheme> NodeDescriptorBuilder.scheme(
property: KProperty1<S, T>,
spec: SchemeSpec<T>,
noinline block: NodeDescriptor.() -> Unit = {},
) {
spec.descriptor?.let { descriptor ->
item(property.name, descriptor.copy(block))
}
}

View File

@ -1,10 +1,7 @@
package space.kscience.visionforge package space.kscience.visionforge
import space.kscience.dataforge.meta.* import space.kscience.dataforge.meta.*
import space.kscience.dataforge.meta.descriptors.ItemDescriptor import space.kscience.dataforge.meta.descriptors.*
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.names.Name import space.kscience.dataforge.names.Name
import space.kscience.dataforge.values.ValueType import space.kscience.dataforge.values.ValueType
import space.kscience.dataforge.values.asValue 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 INHERITED_DESCRIPTOR_ATTRIBUTE = "inherited"
private const val STYLE_DESCRIPTOR_ATTRIBUTE = "useStyles" 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 get() = attributes[INHERITED_DESCRIPTOR_ATTRIBUTE].boolean ?: false
set(value) = attributes { set(value) = attributes {
set(INHERITED_DESCRIPTOR_ATTRIBUTE, value) 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 get() = attributes[STYLE_DESCRIPTOR_ATTRIBUTE].boolean ?: true
set(value) = attributes { set(value) = attributes {
set(STYLE_DESCRIPTOR_ATTRIBUTE, value) 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] * 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 get() = attributes["widget"].node ?: Meta.EMPTY
set(value) { set(value) {
attributes { 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] * 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 get() = attributes["widget.type"].string
set(value) { set(value) {
attributes { attributes {
@ -60,15 +69,15 @@ public var ValueDescriptor.widgetType: String?
public val ItemDescriptor.hidden: Boolean public val ItemDescriptor.hidden: Boolean
get() = attributes["widget.hide"].boolean ?: false get() = attributes["widget.hide"].boolean ?: false
public fun ItemDescriptor.hide(): Unit = attributes { public fun ItemDescriptorBuilder.hide(): Unit = attributes {
set("widget.hide", true) set("widget.hide", true)
} }
public inline fun <reified E : Enum<E>> NodeDescriptor.enum( public inline fun <reified E : Enum<E>> NodeDescriptorBuilder.enum(
key: Name, key: Name,
default: E?, default: E?,
crossinline modifier: ValueDescriptor.() -> Unit = {}, crossinline modifier: ValueDescriptorBuilder.() -> Unit = {},
): Unit = value(key) { ): Unit = value(key) {
type(ValueType.STRING) type(ValueType.STRING)
default?.let { default?.let {

View File

@ -46,7 +46,7 @@ class HtmlTagTest {
} }
} }
val groupRenderer: HtmlVisionRenderer = { _, group, _ -> val groupRenderer: HtmlVisionRenderer = { _, _, _ ->
p { +"This is group" } p { +"This is group" }
} }

View File

@ -2,10 +2,7 @@ package space.kscience.visionforge
import kotlinx.browser.document import kotlinx.browser.document
import kotlinx.browser.window import kotlinx.browser.window
import org.w3c.dom.Element import org.w3c.dom.*
import org.w3c.dom.WebSocket
import org.w3c.dom.asList
import org.w3c.dom.get
import org.w3c.dom.url.URL import org.w3c.dom.url.URL
import space.kscience.dataforge.context.* import space.kscience.dataforge.context.*
import space.kscience.dataforge.meta.Meta 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. * 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") val name = resolveName(element) ?: error("The element is not a vision output")
logger.info { "Found DF output with name $name" } logger.info { "Found DF output with name $name" }
if (!element.classList.contains(VisionTagConsumer.OUTPUT_CLASS)) error("The element $element is not an output element") 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]. private fun whenDocumentLoaded(block: Document.() -> Unit): Unit {
*/ if (document.readyState == DocumentReadyState.COMPLETE) {
public fun VisionClient.renderAllVisionsAt(element: Element) { block(document)
val elements = element.getElementsByClassName(VisionTagConsumer.OUTPUT_CLASS) } else {
console.info("Finished search for outputs. Found ${elements.length} items") document.addEventListener("DOMContentLoaded", { block(document) })
elements.asList().forEach { child ->
renderVisionAt(child)
} }
} }
/**
* 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 * Fetch visions from the server for all elements with [VisionTagConsumer.OUTPUT_CLASS] class in the document body
*/ */
public fun VisionClient.renderAllVisions() { public fun VisionClient.renderAllVisions(): Unit = whenDocumentLoaded {
val element = document.body ?: error("Document does not have a body") val element = body ?: error("Document does not have a body")
renderAllVisionsAt(element) 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()
} }

View File

@ -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)
//}

View File

@ -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<out VisionPlugin>, block: VisionForge.() -> Unit): Unit {
modules.forEach {
plugins.fetch(it)
}
run(block)
}

View File

@ -1,4 +1,5 @@
plugins { plugins {
kotlin("multiplatform")
id("ru.mipt.npm.gradle.mpp") id("ru.mipt.npm.gradle.mpp")
} }
@ -7,7 +8,7 @@ kotlin {
val commonMain by getting { val commonMain by getting {
dependencies { dependencies {
api(project(":visionforge-solid")) api(project(":visionforge-solid"))
api("space.kscience:gdml:0.3.2") api("space.kscience:gdml:0.4.0")
} }
} }
} }

View File

@ -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
}
}
}
}
}
}
}
}
}

View File

@ -35,13 +35,13 @@ public class GdmlTransformerSettings {
PROTOTYPE PROTOTYPE
} }
public var lUnit: LUnit = LUnit.CM public var lUnit: LUnit = LUnit.MM
public var aUnit: AUnit = AUnit.RADIAN public var aUnit: AUnit = AUnit.RADIAN
public var solidAction: (GdmlSolid) -> Action = { Action.PROTOTYPE } public var solidAction: (GdmlSolid) -> Action = { Action.PROTOTYPE }
public var volumeAction: (GdmlGroup) -> 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)) color(random.nextInt(16777216))
} }
} }
@ -110,7 +110,7 @@ private class GdmlTransformer(val settings: GdmlTransformerSettings) {
val styleName = "materials.${material.name}" val styleName = "materials.${material.name}"
obj.useStyle(styleName) { obj.useStyle(styleName) {
val vfMaterial = settings.run { SolidMaterial().apply { paint(material)}} val vfMaterial = settings.run { SolidMaterial().apply { paint(material) } }
MATERIAL_KEY put vfMaterial.toMeta() MATERIAL_KEY put vfMaterial.toMeta()
"Gdml.material" put material.name "Gdml.material" put material.name
} }
@ -151,6 +151,24 @@ private class GdmlTransformer(val settings: GdmlTransformerSettings) {
physVolume.resolveScale(root) 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( fun SolidGroup.addSolid(
root: Gdml, root: Gdml,
solid: GdmlSolid, solid: GdmlSolid,
@ -158,7 +176,7 @@ private class GdmlTransformer(val settings: GdmlTransformerSettings) {
): Solid { ): Solid {
//context.solidAdded(solid) //context.solidAdded(solid)
val lScale = solid.lscale(settings.lUnit) val lScale = solid.lscale(settings.lUnit)
val aScale = solid.ascale() val aScale = solid.ascale(settings.aUnit)
return when (solid) { return when (solid) {
is GdmlBox -> box(solid.x * lScale, solid.y * lScale, solid.z * lScale, name) is GdmlBox -> box(solid.x * lScale, solid.y * lScale, solid.z * lScale, name)
is GdmlTube -> tube( is GdmlTube -> tube(
@ -299,7 +317,7 @@ private class GdmlTransformer(val settings: GdmlTransformerSettings) {
when (settings.volumeAction(volume)) { when (settings.volumeAction(volume)) {
GdmlTransformerSettings.Action.ADD -> { GdmlTransformerSettings.Action.ADD -> {
val group: SolidGroup = volume(root, volume) val group: SolidGroup = volume(root, volume)
this[physVolume.name ?: ""] = group.withPosition(root, physVolume) this[physVolume.name] = group.withPosition(root, physVolume)
} }
GdmlTransformerSettings.Action.PROTOTYPE -> { GdmlTransformerSettings.Action.PROTOTYPE -> {
proxyVolume(root, this, physVolume, volume) proxyVolume(root, this, physVolume, volume)
@ -378,7 +396,7 @@ private class GdmlTransformer(val settings: GdmlTransformerSettings) {
return final 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")))
} }

View File

@ -2,12 +2,8 @@ package space.kscience.visionforge.gdml
import space.kscience.dataforge.context.Context import space.kscience.dataforge.context.Context
import space.kscience.dataforge.names.toName import space.kscience.dataforge.names.toName
import space.kscience.gdml.Gdml import space.kscience.gdml.*
import space.kscience.gdml.GdmlBox
import space.kscience.gdml.decodeFromString
import space.kscience.gdml.encodeToString
import space.kscience.visionforge.Vision import space.kscience.visionforge.Vision
import space.kscience.visionforge.gdml.GdmlShowcase.cubes
import space.kscience.visionforge.get import space.kscience.visionforge.get
import space.kscience.visionforge.solid.* import space.kscience.visionforge.solid.*
import space.kscience.visionforge.visionManager import space.kscience.visionforge.visionManager
@ -21,13 +17,16 @@ internal val testContext = Context("TEST") {
class TestCubes { class TestCubes {
val cubes = GdmlShowCase.cubes()
@Test @Test
fun testCubesDirect() { fun testCubesDirect() {
val vision = cubes.toVision() val vision = cubes.toVision()
// println(Solids.encodeToString(vision))
val smallBoxPrototype = vision.getPrototype("solids.smallBox".toName()) as? Box val smallBoxPrototype = vision.getPrototype("solids.smallBox".toName()) as? Box
assertNotNull(smallBoxPrototype) assertNotNull(smallBoxPrototype)
assertEquals(30.0, smallBoxPrototype.xSize.toDouble()) 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) assertNotNull(smallBoxVision)
assertEquals(30.0, smallBoxVision.xSize.toDouble()) assertEquals(30.0, smallBoxVision.xSize.toDouble())
} }

View File

@ -4,6 +4,7 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import nl.adaptivity.xmlutil.StAXReader import nl.adaptivity.xmlutil.StAXReader
import space.kscience.gdml.Gdml import space.kscience.gdml.Gdml
import space.kscience.gdml.decodeFromReader
import space.kscience.visionforge.solid.prototype import space.kscience.visionforge.solid.prototype
import space.kscience.visionforge.visitor.countDistinct import space.kscience.visionforge.visitor.countDistinct
import space.kscience.visionforge.visitor.flowStatistics 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() File("D:\\Work\\Projects\\dataforge-vis\\visionforge-gdml\\src\\jvmTest\\resources\\gdml\\BM@N.gdml").inputStream()
val xmlReader = StAXReader(stream, "UTF-8") val xmlReader = StAXReader(stream, "UTF-8")
val xml = Gdml.format.decodeFromReader(Gdml.serializer(), xmlReader) val xml = Gdml.decodeFromReader( xmlReader)
val vision = xml.toVision() val vision = xml.toVision()

View File

@ -4,12 +4,12 @@ plugins {
val plotlyVersion = "0.4.0-dev-1" val plotlyVersion = "0.4.0-dev-1"
kscience{ kscience {
useSerialization() useSerialization()
} }
kotlin { kotlin {
js{ js {
//binaries.library() //binaries.library()
binaries.executable() binaries.executable()
browser { browser {
@ -19,16 +19,12 @@ kotlin {
} }
} }
afterEvaluate {
val jsBrowserDistribution by tasks.getting val jsBrowserDistribution by tasks.getting
tasks.getByName<ProcessResources>("jvmProcessResources") { tasks.getByName<ProcessResources>("jvmProcessResources") {
dependsOn(jsBrowserDistribution) dependsOn(jsBrowserDistribution)
afterEvaluate {
from(jsBrowserDistribution) from(jsBrowserDistribution)
} }
}
}
sourceSets { sourceSets {
commonMain { commonMain {

View File

@ -4,14 +4,11 @@ import kotlinx.serialization.modules.SerializersModule
import kotlinx.serialization.modules.polymorphic import kotlinx.serialization.modules.polymorphic
import kotlinx.serialization.modules.subclass import kotlinx.serialization.modules.subclass
import space.kscience.dataforge.context.PluginFactory import space.kscience.dataforge.context.PluginFactory
import space.kscience.dataforge.misc.DFExperimental
import space.kscience.visionforge.Vision import space.kscience.visionforge.Vision
import space.kscience.visionforge.VisionForge
import space.kscience.visionforge.VisionPlugin import space.kscience.visionforge.VisionPlugin
import space.kscience.visionforge.plugins
public expect class PlotlyPlugin : VisionPlugin{ public expect class PlotlyPlugin : VisionPlugin {
public companion object: PluginFactory<PlotlyPlugin> public companion object : PluginFactory<PlotlyPlugin>
} }
internal val plotlySerializersModule = SerializersModule { internal val plotlySerializersModule = SerializersModule {
@ -19,11 +16,3 @@ internal val plotlySerializersModule = SerializersModule {
subclass(VisionOfPlotly.serializer()) subclass(VisionOfPlotly.serializer())
} }
} }
/**
* Ensure that [PlotlyPlugin] is loaded in the global [VisionForge] context
*/
@DFExperimental
public fun VisionForge.usePlotly() {
plugins.fetch(PlotlyPlugin)
}

View File

@ -1,30 +1,22 @@
package space.kscience.visionforge.plotly package space.kscience.visionforge.plotly
import kotlinx.html.script //internal val plotlyScriptLocation = "js/visionforge-three.js"
import kotlinx.html.unsafe //
import space.kscience.dataforge.misc.DFExperimental ///**
import space.kscience.visionforge.html.HtmlFragment // * A header that stores/embeds plotly bundle and registers plotly renderer in the frontend
import space.kscience.visionforge.html.ResourceLocation // */
import space.kscience.visionforge.html.scriptHeader //@OptIn(DFExperimental::class)
import java.nio.file.Path //public fun plotlyHeader(location: ResourceLocation, filePath: Path? = null): HtmlFragment = {
// scriptHeader(
internal val plotlyScriptLocation = "js/visionforge-three.js" // plotlyScriptLocation,
// resourceLocation = location,
/** // htmlPath = filePath
* A header that stores/embeds plotly bundle and registers plotly renderer in the frontend // ).invoke(this)
*/ // script {
@OptIn(DFExperimental::class) // type = "text/javascript"
public fun plotlyHeader(location: ResourceLocation, filePath: Path? = null): HtmlFragment = { // unsafe {
scriptHeader( // //language=JavaScript
plotlyScriptLocation, // +"space.kscience.visionforge.plotly.loadPlotly()"
resourceLocation = location, // }
htmlPath = filePath // }
).invoke(this) //}
script {
type = "text/javascript"
unsafe {
//language=JavaScript
+"space.kscience.visionforge.plotly.loadPlotly()"
}
}
}

View File

@ -17,9 +17,7 @@ import kotlin.reflect.KClass
public class Solids(meta: Meta) : VisionPlugin(meta) { public class Solids(meta: Meta) : VisionPlugin(meta) {
override val tag: PluginTag get() = Companion.tag override val tag: PluginTag get() = Companion.tag
override val visionSerializersModule: SerializersModule get() = serializersModuleForSolids override val visionSerializersModule: SerializersModule get() = serializersModuleForSolids
public companion object : PluginFactory<Solids> { public companion object : PluginFactory<Solids> {

View File

@ -9,6 +9,9 @@ import kotlin.math.PI
import kotlin.math.cos import kotlin.math.cos
import kotlin.math.sin import kotlin.math.sin
/**
* A spherical layer
*/
@Serializable @Serializable
@SerialName("solid.sphereLayer") @SerialName("solid.sphereLayer")
public class SphereLayer( public class SphereLayer(

View File

@ -3,7 +3,9 @@ package space.kscience.visionforge.solid.specifications
import space.kscience.dataforge.meta.Scheme import space.kscience.dataforge.meta.Scheme
import space.kscience.dataforge.meta.SchemeSpec import space.kscience.dataforge.meta.SchemeSpec
import space.kscience.dataforge.meta.boolean import space.kscience.dataforge.meta.boolean
import space.kscience.dataforge.meta.descriptors.NodeDescriptor
import space.kscience.dataforge.meta.double import space.kscience.dataforge.meta.double
import space.kscience.visionforge.value
public class Axes : Scheme() { public class Axes : Scheme() {
public var visible: Boolean by boolean(false) public var visible: Boolean by boolean(false)
@ -13,5 +15,13 @@ public class Axes : Scheme() {
public companion object : SchemeSpec<Axes>(::Axes) { public companion object : SchemeSpec<Axes>(::Axes) {
public const val AXIS_SIZE: Double = 1000.0 public const val AXIS_SIZE: Double = 1000.0
public const val AXIS_WIDTH: Double = 3.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)
}
}
} }
} }

View File

@ -2,8 +2,10 @@ package space.kscience.visionforge.solid.specifications
import space.kscience.dataforge.meta.Scheme import space.kscience.dataforge.meta.Scheme
import space.kscience.dataforge.meta.SchemeSpec import space.kscience.dataforge.meta.SchemeSpec
import space.kscience.dataforge.meta.descriptors.NodeDescriptor
import space.kscience.dataforge.meta.double import space.kscience.dataforge.meta.double
import space.kscience.dataforge.meta.int import space.kscience.dataforge.meta.int
import space.kscience.visionforge.value
import kotlin.math.PI import kotlin.math.PI
public class Camera : Scheme() { public class Camera : Scheme() {
@ -25,5 +27,16 @@ public class Camera : Scheme() {
public const val NEAR_CLIP: Double = 0.1 public const val NEAR_CLIP: Double = 0.1
public const val FAR_CLIP: Double = 10000.0 public const val FAR_CLIP: Double = 10000.0
public const val FIELD_OF_VIEW: Int = 75 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)
}
}
} }
} }

View File

@ -1,7 +1,10 @@
package space.kscience.visionforge.solid.specifications package space.kscience.visionforge.solid.specifications
import space.kscience.dataforge.meta.* import space.kscience.dataforge.meta.*
import space.kscience.dataforge.meta.descriptors.NodeDescriptor
import space.kscience.dataforge.names.Name import space.kscience.dataforge.names.Name
import space.kscience.visionforge.scheme
import space.kscience.visionforge.value
public class Canvas3DOptions : Scheme() { public class Canvas3DOptions : Scheme() {
public var axes: Axes by spec(Axes) public var axes: Axes by spec(Axes)
@ -17,10 +20,25 @@ public class Canvas3DOptions : Scheme() {
public var maxWith: Number by number { maxSize } public var maxWith: Number by number { maxSize }
public var maxHeight: 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>(::Canvas3DOptions) public companion object : SchemeSpec<Canvas3DOptions>(::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 = public fun Canvas3DOptions.computeWidth(external: Number): Int =

View File

@ -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!!
}
}
}

View File

@ -11,5 +11,5 @@ kotlin{
dependencies { dependencies {
api(project(":visionforge-solid")) api(project(":visionforge-solid"))
implementation(npm("three", "0.124.0")) implementation(npm("three", "0.124.0"))
implementation(npm("three-csg-ts", "2.2.0")) implementation(npm("three-csg-ts", "2.2.2"))
} }

View File

@ -28,6 +28,7 @@
package info.laht.threekt.renderers package info.laht.threekt.renderers
import info.laht.threekt.cameras.Camera import info.laht.threekt.cameras.Camera
import info.laht.threekt.math.Plane
import info.laht.threekt.scenes.Scene import info.laht.threekt.scenes.Scene
import org.w3c.dom.Node import org.w3c.dom.Node
@ -103,4 +104,17 @@ external class WebGLRenderer(params: WebGLRendererParams = definedExternally) {
) )
fun setPixelRatio(value: Number) 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<Plane>
/**
* Defines whether the renderer respects object-level clipping planes. Default is false.
*/
var localClippingEnabled: Boolean
} }

View File

@ -23,6 +23,7 @@ import space.kscience.dataforge.context.info
import space.kscience.dataforge.context.logger import space.kscience.dataforge.context.logger
import space.kscience.dataforge.meta.get import space.kscience.dataforge.meta.get
import space.kscience.dataforge.meta.string import space.kscience.dataforge.meta.string
import space.kscience.dataforge.meta.useProperty
import space.kscience.dataforge.names.Name import space.kscience.dataforge.names.Name
import space.kscience.dataforge.names.asName import space.kscience.dataforge.names.asName
import space.kscience.dataforge.names.plus import space.kscience.dataforge.names.plus
@ -50,14 +51,23 @@ public class ThreeCanvas(
public var content: Solid? = null public var content: Solid? = null
private set 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 { private val scene: Scene = Scene().apply {
add(axes) options.useProperty(Canvas3DOptions::axes){axesConfig->
add(light) 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) public var camera: PerspectiveCamera = buildCamera(options.camera)
@ -138,7 +148,7 @@ public class ThreeCanvas(
} }
internal fun attach(element: Element) { 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) element.appendChild(canvas)
updateSize() 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( private fun buildCamera(spec: Camera) = PerspectiveCamera(
spec.fov, spec.fov,
@ -262,5 +272,7 @@ public class ThreeCanvas(
public const val DO_NOT_HIGHLIGHT_TAG: String = "doNotHighlight" public const val DO_NOT_HIGHLIGHT_TAG: String = "doNotHighlight"
private const val HIGHLIGHT_NAME = "@highlight" private const val HIGHLIGHT_NAME = "@highlight"
private const val SELECT_NAME = "@select" private const val SELECT_NAME = "@select"
private const val LIGHT_NAME = "@light"
private const val AXES_NAME = "@axes"
} }
} }

View File

@ -8,11 +8,13 @@ import org.w3c.dom.Element
import org.w3c.dom.HTMLElement import org.w3c.dom.HTMLElement
import space.kscience.dataforge.context.* import space.kscience.dataforge.context.*
import space.kscience.dataforge.meta.Meta import space.kscience.dataforge.meta.Meta
import space.kscience.dataforge.misc.DFExperimental
import space.kscience.dataforge.names.* 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.*
import space.kscience.visionforge.solid.specifications.Canvas3DOptions import space.kscience.visionforge.solid.specifications.Canvas3DOptions
import space.kscience.visionforge.visible
import kotlin.collections.set import kotlin.collections.set
import kotlin.reflect.KClass import kotlin.reflect.KClass
import info.laht.threekt.objects.Group as ThreeGroup 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( public fun ThreePlugin.render(
element: HTMLElement, element: HTMLElement,
obj: Solid, obj: Solid,

View File

@ -1,14 +1,11 @@
package space.kscience.visionforge.three.server package space.kscience.visionforge.three.server
import kotlinx.browser.window
import space.kscience.dataforge.misc.DFExperimental import space.kscience.dataforge.misc.DFExperimental
import space.kscience.visionforge.VisionForge import space.kscience.visionforge.runVisionClient
import space.kscience.visionforge.solid.three.useThreeJs import space.kscience.visionforge.solid.three.ThreePlugin
@DFExperimental @DFExperimental
public fun main(): Unit = VisionForge.run { public fun main(): Unit = runVisionClient {
console.info("Starting VisionForge context") plugin(ThreePlugin)
useThreeJs()
window.asDynamic()["VisionForge"] = VisionForge
renderVisionsInWindow()
} }

View File

@ -1,7 +1,7 @@
package space.kscience.visionforge.three.server package space.kscience.visionforge.three.server
import space.kscience.dataforge.context.Context
import space.kscience.dataforge.misc.DFExperimental import space.kscience.dataforge.misc.DFExperimental
import space.kscience.visionforge.VisionForge
import space.kscience.visionforge.html.HtmlVisionFragment import space.kscience.visionforge.html.HtmlVisionFragment
import space.kscience.visionforge.html.ResourceLocation import space.kscience.visionforge.html.ResourceLocation
import space.kscience.visionforge.html.page import space.kscience.visionforge.html.page
@ -16,7 +16,7 @@ public fun VisionServer.useThreeJs(): Unit {
} }
@DFExperimental @DFExperimental
public fun VisionForge.makeThreeJsFile( public fun Context.makeThreeJsFile(
content: HtmlVisionFragment, content: HtmlVisionFragment,
path: Path? = null, path: Path? = null,
title: String = "VisionForge page", title: String = "VisionForge page",