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 {
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 {

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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<VisionForge>()
render<Gdml> { gdmlModel ->
val fragment = VisionForge.fragment {
val fragment = HtmlVisionFragment {
vision(gdmlModel.toVision())
}
HTML(produceHtmlVisionString(fragment))
}
render<Vision> { vision ->
val fragment = VisionForge.fragment {
val fragment = HtmlVisionFragment {
vision(vision)
}
@ -83,7 +79,7 @@ internal class VisionForgePlayGroundForJupyter : JupyterIntegration() {
}
render<Plot> { plot ->
val fragment = VisionForge.fragment {
val fragment = HtmlVisionFragment {
vision(plot.toVision())
}

View File

@ -22,6 +22,7 @@ kotlin {
tasks.getByName<ProcessResources>("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<org.jetbrains.kotlin.gradle.dsl.KotlinJsCompile>(){
kotlinOptions{
freeCompilerArgs = freeCompilerArgs + "-Xir-property-lazy-initialization"
}
}
//distributions {
// main {
// 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 context = Global.context("demo") {}
val context = Global.buildContext("demo") {}
render(element) {
child(MMApp) {
attrs {

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

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
fun main() {
val satContext = Global.context("sat") {
val satContext = Global.buildContext ("sat") {
plugin(Solids)
}

View File

@ -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
kotlin.native.enableDependencyPropagation=false
kotlin.parallel.tasks.in.project=true
org.gradle.jvmargs=-XX:MaxMetaspaceSize=1G
org.gradle.parallel=true

View File

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

View File

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

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.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<VisionForge>()
render<Gdml> { gdmlModel ->
val fragment = VisionForge.fragment {
val fragment = HtmlVisionFragment {
vision(gdmlModel.toVision())
}
HTML(produceHtmlVisionString(fragment))
}
render<Vision> { vision ->
val fragment = VisionForge.fragment {
val fragment = HtmlVisionFragment {
vision(vision)
}

View File

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

View File

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

View File

@ -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<CanvasControlsProps> = 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<CanvasControlsProps> = 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<CanvasControlsProps> = functional
}
}
}
*/
}
}

View File

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

View File

@ -59,6 +59,11 @@ public external interface PropertyEditorProps : RProps {
* Flow names of updated properties
*/
public var updateFlow: Flow<Name>?
/**
* Initial expanded state
*/
public var expanded: Boolean?
}
private val PropertyEditorItem: FunctionalComponent<PropertyEditorProps> =
@ -67,7 +72,7 @@ private val PropertyEditorItem: FunctionalComponent<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)
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<PropertyEditorProps> = functional
public fun RBuilder.propertyEditor(
ownProperties: MutableItemProvider,
allProperties: ItemProvider?,
allProperties: ItemProvider? = ownProperties,
updateFlow: Flow<Name>? = 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
}
}
}

View File

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

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.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
public fun HtmlVisionFragment(content: VisionTagConsumer<*>.() -> Unit): HtmlVisionFragment = content

View File

@ -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<String, HtmlFragment>,
public val content: HtmlVisionFragment
public val content: HtmlVisionFragment,
) {
public fun <R> render(root: TagConsumer<R>): 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<String, HtmlFragment>,
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)
}
/**
* TODO to be replaced by multi-receiver
*/
@OptIn(DFExperimental::class)
public inline fun <T> TagConsumer<T>.vision(
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
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 <reified E : Enum<E>> NodeDescriptor.enum(
public inline fun <reified E : Enum<E>> NodeDescriptorBuilder.enum(
key: Name,
default: E?,
crossinline modifier: ValueDescriptor.() -> Unit = {},
crossinline modifier: ValueDescriptorBuilder.() -> Unit = {},
): Unit = value(key) {
type(ValueType.STRING)
default?.let {

View File

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

View File

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

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 {
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")
}
}
}

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
}
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")))
}

View File

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

View File

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

View File

@ -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<ProcessResources>("jvmProcessResources") {
dependsOn(jsBrowserDistribution)
afterEvaluate {
from(jsBrowserDistribution)
}
}
tasks.getByName<ProcessResources>("jvmProcessResources") {
dependsOn(jsBrowserDistribution)
from(jsBrowserDistribution)
}
sourceSets {

View File

@ -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<PlotlyPlugin>
public expect class PlotlyPlugin : VisionPlugin {
public companion object : PluginFactory<PlotlyPlugin>
}
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)
}

View File

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

View File

@ -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<Solids> {

View File

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

View File

@ -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>(::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)
}
}
}
}

View File

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

View File

@ -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>(::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 =
(external.toInt()).coerceIn(minWith.toInt()..maxWith.toInt())
public fun Canvas3DOptions.computeHeight(external: Number): Int =
(external.toInt()).coerceIn(minHeight.toInt()..maxHeight.toInt())
(external.toInt()).coerceIn(minHeight.toInt()..maxHeight.toInt())

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 {
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"))
}

View File

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

View File

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

View File

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

View File

@ -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",