forked from kscience/visionforge
Fix after dev merge.
This commit is contained in:
parent
33146fef1b
commit
0c1d6139ae
@ -1,9 +1,9 @@
|
|||||||
package hep.dataforge.vision.gdml.demo
|
package hep.dataforge.vision.gdml.demo
|
||||||
|
|
||||||
import hep.dataforge.Application
|
|
||||||
import hep.dataforge.context.Global
|
import hep.dataforge.context.Global
|
||||||
import hep.dataforge.startApplication
|
import hep.dataforge.vision.Application
|
||||||
import hep.dataforge.vision.gdml.toVision
|
import hep.dataforge.vision.gdml.toVision
|
||||||
|
import hep.dataforge.vision.startApplication
|
||||||
import kotlinx.browser.document
|
import kotlinx.browser.document
|
||||||
import react.child
|
import react.child
|
||||||
import react.dom.render
|
import react.dom.render
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
package ru.mipt.npm.muon.monitor
|
package ru.mipt.npm.muon.monitor
|
||||||
|
|
||||||
import hep.dataforge.Application
|
|
||||||
import hep.dataforge.context.Global
|
import hep.dataforge.context.Global
|
||||||
import hep.dataforge.startApplication
|
import hep.dataforge.vision.Application
|
||||||
|
import hep.dataforge.vision.startApplication
|
||||||
import io.ktor.client.HttpClient
|
import io.ktor.client.HttpClient
|
||||||
import io.ktor.client.features.json.JsonFeature
|
import io.ktor.client.features.json.JsonFeature
|
||||||
import io.ktor.client.features.json.serializer.KotlinxSerializer
|
import io.ktor.client.features.json.serializer.KotlinxSerializer
|
||||||
|
@ -4,7 +4,7 @@ import hep.dataforge.meta.Meta
|
|||||||
import hep.dataforge.meta.invoke
|
import hep.dataforge.meta.invoke
|
||||||
import hep.dataforge.names.toName
|
import hep.dataforge.names.toName
|
||||||
import hep.dataforge.vision.Colors
|
import hep.dataforge.vision.Colors
|
||||||
import hep.dataforge.vision.layout.Page
|
import hep.dataforge.vision.VisionLayout
|
||||||
import hep.dataforge.vision.solid.*
|
import hep.dataforge.vision.solid.*
|
||||||
import hep.dataforge.vision.solid.specifications.Canvas3DOptions
|
import hep.dataforge.vision.solid.specifications.Canvas3DOptions
|
||||||
import hep.dataforge.vision.visible
|
import hep.dataforge.vision.visible
|
||||||
@ -15,12 +15,12 @@ import kotlin.math.sin
|
|||||||
import kotlin.random.Random
|
import kotlin.random.Random
|
||||||
|
|
||||||
|
|
||||||
fun Page<Solid>.demo(name: String, title: String = name, block: SolidGroup.() -> Unit) {
|
fun VisionLayout<Solid>.demo(name: String, title: String = name, block: SolidGroup.() -> Unit) {
|
||||||
val meta = Meta {
|
val meta = Meta {
|
||||||
"title" put title
|
"title" put title
|
||||||
}
|
}
|
||||||
val output = output(name.toName(), meta)?: error("Output with name $name not found")
|
val vision = SolidGroup(block)
|
||||||
output.solidGroup (builder = block)
|
render(name.toName(), vision)
|
||||||
}
|
}
|
||||||
|
|
||||||
val canvasOptions = Canvas3DOptions {
|
val canvasOptions = Canvas3DOptions {
|
||||||
@ -35,7 +35,7 @@ val canvasOptions = Canvas3DOptions {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun Page<Solid>.showcase() {
|
fun VisionLayout<Solid>.showcase() {
|
||||||
demo("shapes", "Basic shapes") {
|
demo("shapes", "Basic shapes") {
|
||||||
box(100.0, 100.0, 100.0) {
|
box(100.0, 100.0, 100.0) {
|
||||||
z = -110.0
|
z = -110.0
|
||||||
@ -136,14 +136,14 @@ fun Page<Solid>.showcase() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun Page<Solid>.showcaseCSG() {
|
fun VisionLayout<Solid>.showcaseCSG() {
|
||||||
demo("CSG.simple", "CSG operations") {
|
demo("CSG.simple", "CSG operations") {
|
||||||
composite(CompositeType.INTERSECT) {
|
composite(CompositeType.INTERSECT) {
|
||||||
y = 300
|
y = 300
|
||||||
box(100, 100, 100) {
|
box(100, 100, 100) {
|
||||||
z = 50
|
z = 50
|
||||||
}
|
}
|
||||||
sphere(50){
|
sphere(50) {
|
||||||
detail = 32
|
detail = 32
|
||||||
}
|
}
|
||||||
material {
|
material {
|
||||||
@ -154,7 +154,7 @@ fun Page<Solid>.showcaseCSG() {
|
|||||||
box(100, 100, 100) {
|
box(100, 100, 100) {
|
||||||
z = 50
|
z = 50
|
||||||
}
|
}
|
||||||
sphere(50){
|
sphere(50) {
|
||||||
detail = 32
|
detail = 32
|
||||||
}
|
}
|
||||||
color("lightgreen")
|
color("lightgreen")
|
||||||
@ -165,7 +165,7 @@ fun Page<Solid>.showcaseCSG() {
|
|||||||
box(100, 100, 100) {
|
box(100, 100, 100) {
|
||||||
z = 50
|
z = 50
|
||||||
}
|
}
|
||||||
sphere(50){
|
sphere(50) {
|
||||||
detail = 32
|
detail = 32
|
||||||
}
|
}
|
||||||
color("teal")
|
color("teal")
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
package hep.dataforge.vision.solid.demo
|
package hep.dataforge.vision.solid.demo
|
||||||
|
|
||||||
import hep.dataforge.Application
|
import hep.dataforge.vision.Application
|
||||||
import hep.dataforge.startApplication
|
|
||||||
import hep.dataforge.vision.solid.x
|
import hep.dataforge.vision.solid.x
|
||||||
import hep.dataforge.vision.solid.y
|
import hep.dataforge.vision.solid.y
|
||||||
|
import hep.dataforge.vision.startApplication
|
||||||
import kotlinx.browser.document
|
import kotlinx.browser.document
|
||||||
import kotlinx.coroutines.GlobalScope
|
import kotlinx.coroutines.GlobalScope
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
|
@ -5,8 +5,7 @@ import hep.dataforge.meta.Meta
|
|||||||
import hep.dataforge.meta.get
|
import hep.dataforge.meta.get
|
||||||
import hep.dataforge.meta.string
|
import hep.dataforge.meta.string
|
||||||
import hep.dataforge.names.Name
|
import hep.dataforge.names.Name
|
||||||
import hep.dataforge.vision.layout.Output
|
import hep.dataforge.vision.VisionLayout
|
||||||
import hep.dataforge.vision.layout.Page
|
|
||||||
import hep.dataforge.vision.solid.Solid
|
import hep.dataforge.vision.solid.Solid
|
||||||
import hep.dataforge.vision.solid.three.ThreeCanvas
|
import hep.dataforge.vision.solid.three.ThreeCanvas
|
||||||
import hep.dataforge.vision.solid.three.ThreePlugin
|
import hep.dataforge.vision.solid.three.ThreePlugin
|
||||||
@ -20,7 +19,7 @@ import org.w3c.dom.Element
|
|||||||
import org.w3c.dom.HTMLDivElement
|
import org.w3c.dom.HTMLDivElement
|
||||||
import org.w3c.dom.HTMLElement
|
import org.w3c.dom.HTMLElement
|
||||||
|
|
||||||
class ThreeDemoGrid(element: Element) : Page<Solid> {
|
class ThreeDemoGrid(element: Element) : VisionLayout<Solid> {
|
||||||
private lateinit var navigationElement: HTMLElement
|
private lateinit var navigationElement: HTMLElement
|
||||||
private lateinit var contentElement: HTMLDivElement
|
private lateinit var contentElement: HTMLDivElement
|
||||||
|
|
||||||
@ -47,31 +46,31 @@ class ThreeDemoGrid(element: Element) : Page<Solid> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun render(name: Name, vision: Solid, meta: Meta) {
|
||||||
@Suppress("UNCHECKED_CAST")
|
outputs.getOrPut(name) {
|
||||||
override fun output(name: Name, meta: Meta): Output<Solid> = outputs.getOrPut(name) {
|
navigationElement.append {
|
||||||
navigationElement.append {
|
li("nav-item") {
|
||||||
li("nav-item") {
|
a(classes = "nav-link") {
|
||||||
a(classes = "nav-link") {
|
href = "#$name"
|
||||||
href = "#$name"
|
+name.toString()
|
||||||
+name.toString()
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
contentElement.append {
|
||||||
contentElement.append {
|
div("container") {
|
||||||
div("container") {
|
id = name.toString()
|
||||||
id = name.toString()
|
hr()
|
||||||
hr()
|
h2 { +(meta["title"].string ?: name.toString()) }
|
||||||
h2 { +(meta["title"].string ?: name.toString()) }
|
hr()
|
||||||
hr()
|
div {
|
||||||
div {
|
style = "height: 600px;"
|
||||||
style = "height: 600px;"
|
id = "output-$name"
|
||||||
id = "output-$name"
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
val element = document.getElementById("output-$name") ?: error("Element not found")
|
||||||
val element = document.getElementById("output-$name") ?: error("Element not found")
|
three.createCanvas(element, canvasOptions)
|
||||||
three.createCanvas(element, canvasOptions)
|
}.render(vision)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,8 +3,7 @@ package hep.dataforge.vision.solid.demo
|
|||||||
import hep.dataforge.context.Global
|
import hep.dataforge.context.Global
|
||||||
import hep.dataforge.meta.Meta
|
import hep.dataforge.meta.Meta
|
||||||
import hep.dataforge.names.Name
|
import hep.dataforge.names.Name
|
||||||
import hep.dataforge.vision.layout.Output
|
import hep.dataforge.vision.VisionLayout
|
||||||
import hep.dataforge.vision.layout.Page
|
|
||||||
import hep.dataforge.vision.solid.FX3DPlugin
|
import hep.dataforge.vision.solid.FX3DPlugin
|
||||||
import hep.dataforge.vision.solid.FXCanvas3D
|
import hep.dataforge.vision.solid.FXCanvas3D
|
||||||
import hep.dataforge.vision.solid.Solid
|
import hep.dataforge.vision.solid.Solid
|
||||||
@ -13,7 +12,7 @@ import javafx.scene.Parent
|
|||||||
import javafx.scene.control.Tab
|
import javafx.scene.control.Tab
|
||||||
import tornadofx.*
|
import tornadofx.*
|
||||||
|
|
||||||
class FXDemoGrid : View(title = "DataForge-vis FX demo"), Page<Solid> {
|
class FXDemoGrid : View(title = "DataForge-vis FX demo"), VisionLayout<Solid> {
|
||||||
private val outputs = FXCollections.observableHashMap<Name, FXCanvas3D>()
|
private val outputs = FXCollections.observableHashMap<Name, FXCanvas3D>()
|
||||||
|
|
||||||
override val root: Parent = borderpane {
|
override val root: Parent = borderpane {
|
||||||
@ -26,8 +25,8 @@ class FXDemoGrid : View(title = "DataForge-vis FX demo"), Page<Solid> {
|
|||||||
|
|
||||||
private val fx3d = Global.plugins.fetch(FX3DPlugin)
|
private val fx3d = Global.plugins.fetch(FX3DPlugin)
|
||||||
|
|
||||||
override fun output(name: Name, meta: Meta): Output<Solid> = outputs.getOrPut(name) {
|
override fun render(name: Name, vision: Solid, meta: Meta) {
|
||||||
FXCanvas3D(fx3d, canvasOptions)
|
outputs.getOrPut(name) { FXCanvas3D(fx3d, canvasOptions) }.render(vision)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
@ -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.7.1-bin.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-6.8-bin.zip
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
|
@ -1,2 +0,0 @@
|
|||||||
|
|
||||||
|
|
@ -1,27 +1,9 @@
|
|||||||
import hep.dataforge.context.Context
|
import hep.dataforge.vision.plotly.withPlotly
|
||||||
import hep.dataforge.context.Global
|
import hep.dataforge.vision.renderVisionsInWindow
|
||||||
import hep.dataforge.meta.DFExperimental
|
import hep.dataforge.vision.solid.three.loadThreeJs
|
||||||
import hep.dataforge.vision.client.VisionClient
|
|
||||||
import hep.dataforge.vision.client.renderAllVisions
|
|
||||||
import hep.dataforge.vision.plotly.PlotlyPlugin
|
|
||||||
import hep.dataforge.vision.solid.three.ThreePlugin
|
|
||||||
import kotlinx.browser.window
|
|
||||||
|
|
||||||
@DFExperimental
|
|
||||||
fun main() {
|
fun main() {
|
||||||
|
withPlotly()
|
||||||
val visionContext: Context = Global.context("VISION") {
|
loadThreeJs()
|
||||||
plugin(ThreePlugin)
|
renderVisionsInWindow()
|
||||||
plugin(PlotlyPlugin)
|
|
||||||
plugin(VisionClient)
|
|
||||||
}
|
|
||||||
|
|
||||||
//Loading three-js renderer
|
|
||||||
val clientManager = visionContext.plugins.fetch(VisionClient)
|
|
||||||
|
|
||||||
//Fetch from server and render visions for all outputs
|
|
||||||
window.onload = {
|
|
||||||
clientManager.renderAllVisions()
|
|
||||||
}
|
|
||||||
//startApplication(::PlayGroundApp)
|
|
||||||
}
|
}
|
@ -1,6 +1,8 @@
|
|||||||
package hep.dataforge.vision.solid
|
package hep.dataforge.vision.examples
|
||||||
|
|
||||||
import com.github.ricky12awesome.jss.encodeToSchema
|
import com.github.ricky12awesome.jss.encodeToSchema
|
||||||
|
import hep.dataforge.vision.solid.SolidGroup
|
||||||
|
import hep.dataforge.vision.solid.SolidManager
|
||||||
import kotlinx.serialization.json.Json
|
import kotlinx.serialization.json.Json
|
||||||
|
|
||||||
fun main() {
|
fun main() {
|
@ -1,38 +0,0 @@
|
|||||||
package hep.dataforge.vision.solid
|
|
||||||
|
|
||||||
import hep.dataforge.context.Context
|
|
||||||
import hep.dataforge.context.Global
|
|
||||||
import hep.dataforge.meta.DFExperimental
|
|
||||||
import hep.dataforge.vision.ResourceLocation
|
|
||||||
import hep.dataforge.vision.VisionManager
|
|
||||||
import hep.dataforge.vision.html.HtmlVisionFragment
|
|
||||||
import hep.dataforge.vision.makeVisionFile
|
|
||||||
import hep.dataforge.vision.scriptHeader
|
|
||||||
import hep.dataforge.vision.three.server.VisionServer
|
|
||||||
import hep.dataforge.vision.three.server.useScript
|
|
||||||
import java.nio.file.Path
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A global vision context used to resolve different vision renderers
|
|
||||||
*/
|
|
||||||
@DFExperimental
|
|
||||||
public val VisionForge: Context = Global.context("VISION") {
|
|
||||||
plugin(VisionManager)
|
|
||||||
plugin(SolidManager)
|
|
||||||
}
|
|
||||||
|
|
||||||
public fun VisionServer.usePlayground(): Unit {
|
|
||||||
useScript("js/visionforge-playground.js")
|
|
||||||
}
|
|
||||||
|
|
||||||
@DFExperimental
|
|
||||||
public fun Context.makeVisionFile(
|
|
||||||
fragment: HtmlVisionFragment,
|
|
||||||
path: Path? = null,
|
|
||||||
title: String = "VisionForge page",
|
|
||||||
resourceLocation: ResourceLocation = ResourceLocation.SYSTEM,
|
|
||||||
show: Boolean = true,
|
|
||||||
): Unit = makeVisionFile(fragment, path = path, title = title, show = show) { actualPath ->
|
|
||||||
scriptHeader("js/visionforge-playground.js", actualPath, resourceLocation)
|
|
||||||
}
|
|
@ -1,19 +0,0 @@
|
|||||||
package hep.dataforge.vision.solid
|
|
||||||
|
|
||||||
import hep.dataforge.meta.DFExperimental
|
|
||||||
import hep.dataforge.vision.ResourceLocation
|
|
||||||
import hep.dataforge.vision.VisionManager
|
|
||||||
import hep.dataforge.vision.html.fragment
|
|
||||||
|
|
||||||
@OptIn(DFExperimental::class)
|
|
||||||
fun main() {
|
|
||||||
val fragment = VisionManager.fragment {
|
|
||||||
vision("canvas") {
|
|
||||||
solid {
|
|
||||||
box(100, 100, 100)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
VisionForge.makeVisionFile(fragment = fragment, resourceLocation = ResourceLocation.SYSTEM)
|
|
||||||
}
|
|
25
playground/src/jvmMain/kotlin/plotlyVision.kt
Normal file
25
playground/src/jvmMain/kotlin/plotlyVision.kt
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
package hep.dataforge.vision.examples
|
||||||
|
|
||||||
|
import hep.dataforge.meta.DFExperimental
|
||||||
|
import hep.dataforge.vision.VisionForge
|
||||||
|
import hep.dataforge.vision.VisionManager
|
||||||
|
import hep.dataforge.vision.html.fragment
|
||||||
|
import hep.dataforge.vision.plotly.plotly
|
||||||
|
import hep.dataforge.vision.plotly.withPlotly
|
||||||
|
import kscience.plotly.scatter
|
||||||
|
|
||||||
|
@DFExperimental
|
||||||
|
fun main() {
|
||||||
|
val fragment = VisionManager.fragment {
|
||||||
|
vision {
|
||||||
|
plotly {
|
||||||
|
scatter {
|
||||||
|
x(1,2,3)
|
||||||
|
y(5,8,7)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
VisionForge.withPlotly().makeVisionFile(fragment)
|
||||||
|
}
|
@ -1,9 +1,11 @@
|
|||||||
package hep.dataforge.vision.solid
|
package hep.dataforge.vision.examples
|
||||||
|
|
||||||
import hep.dataforge.meta.DFExperimental
|
import hep.dataforge.meta.DFExperimental
|
||||||
import hep.dataforge.vision.ResourceLocation
|
import hep.dataforge.vision.VisionForge
|
||||||
import hep.dataforge.vision.VisionManager
|
import hep.dataforge.vision.VisionManager
|
||||||
|
import hep.dataforge.vision.html.ResourceLocation
|
||||||
import hep.dataforge.vision.html.fragment
|
import hep.dataforge.vision.html.fragment
|
||||||
|
import hep.dataforge.vision.solid.*
|
||||||
import kotlinx.html.h1
|
import kotlinx.html.h1
|
||||||
import java.nio.file.Paths
|
import java.nio.file.Paths
|
||||||
import kotlin.random.Random
|
import kotlin.random.Random
|
35
playground/src/jvmMain/kotlin/serverExtensions.kt
Normal file
35
playground/src/jvmMain/kotlin/serverExtensions.kt
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
package hep.dataforge.vision.examples
|
||||||
|
|
||||||
|
import hep.dataforge.context.Context
|
||||||
|
import hep.dataforge.meta.DFExperimental
|
||||||
|
import hep.dataforge.vision.html.HtmlVisionFragment
|
||||||
|
import hep.dataforge.vision.html.ResourceLocation
|
||||||
|
import hep.dataforge.vision.html.scriptHeader
|
||||||
|
import hep.dataforge.vision.makeFile
|
||||||
|
import hep.dataforge.vision.page
|
||||||
|
import hep.dataforge.vision.three.server.VisionServer
|
||||||
|
import hep.dataforge.vision.three.server.useScript
|
||||||
|
import java.awt.Desktop
|
||||||
|
import java.nio.file.Path
|
||||||
|
|
||||||
|
|
||||||
|
public fun VisionServer.usePlayground(): Unit {
|
||||||
|
useScript("js/visionforge-playground.js")
|
||||||
|
}
|
||||||
|
|
||||||
|
@DFExperimental
|
||||||
|
public fun Context.makeVisionFile(
|
||||||
|
content: HtmlVisionFragment,
|
||||||
|
path: Path? = null,
|
||||||
|
title: String = "VisionForge page",
|
||||||
|
resourceLocation: ResourceLocation = ResourceLocation.SYSTEM,
|
||||||
|
show: Boolean = true,
|
||||||
|
): Unit {
|
||||||
|
val actualPath = page(title, content).makeFile(path) { actualPath ->
|
||||||
|
mapOf("threeJs" to scriptHeader("js/visionforge-playground.js", actualPath, resourceLocation))
|
||||||
|
}
|
||||||
|
if (show) Desktop.getDesktop().browse(actualPath.toFile().toURI())
|
||||||
|
}
|
||||||
|
// makeVisionFile(fragment, path = path, title = title, show = show) { actualPath ->
|
||||||
|
// scriptHeader("js/visionforge-playground.js", actualPath, resourceLocation)
|
||||||
|
//}
|
22
playground/src/jvmMain/kotlin/simpleCube.kt
Normal file
22
playground/src/jvmMain/kotlin/simpleCube.kt
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
package hep.dataforge.vision.examples
|
||||||
|
|
||||||
|
import hep.dataforge.meta.DFExperimental
|
||||||
|
import hep.dataforge.vision.VisionForge
|
||||||
|
import hep.dataforge.vision.VisionManager
|
||||||
|
import hep.dataforge.vision.html.ResourceLocation
|
||||||
|
import hep.dataforge.vision.html.fragment
|
||||||
|
import hep.dataforge.vision.solid.box
|
||||||
|
import hep.dataforge.vision.solid.solid
|
||||||
|
|
||||||
|
@OptIn(DFExperimental::class)
|
||||||
|
fun main() {
|
||||||
|
val content = VisionManager.fragment {
|
||||||
|
vision("canvas") {
|
||||||
|
solid {
|
||||||
|
box(100, 100, 100)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
VisionForge.makeVisionFile(content, resourceLocation = ResourceLocation.SYSTEM)
|
||||||
|
}
|
@ -0,0 +1,5 @@
|
|||||||
|
package hep.dataforge.vision
|
||||||
|
|
||||||
|
import hep.dataforge.context.Context
|
||||||
|
|
||||||
|
public expect val VisionForge: Context
|
@ -0,0 +1,8 @@
|
|||||||
|
package hep.dataforge.vision
|
||||||
|
|
||||||
|
import hep.dataforge.meta.Meta
|
||||||
|
import hep.dataforge.names.Name
|
||||||
|
|
||||||
|
public interface VisionLayout<in V: Vision> {
|
||||||
|
public fun render(name: Name, vision: V, meta: Meta = Meta.EMPTY)
|
||||||
|
}
|
@ -3,6 +3,8 @@ package hep.dataforge.vision
|
|||||||
import hep.dataforge.context.*
|
import hep.dataforge.context.*
|
||||||
import hep.dataforge.meta.*
|
import hep.dataforge.meta.*
|
||||||
import hep.dataforge.meta.descriptors.NodeDescriptor
|
import hep.dataforge.meta.descriptors.NodeDescriptor
|
||||||
|
import hep.dataforge.names.Name
|
||||||
|
import hep.dataforge.names.toName
|
||||||
import kotlinx.serialization.PolymorphicSerializer
|
import kotlinx.serialization.PolymorphicSerializer
|
||||||
import kotlinx.serialization.json.Json
|
import kotlinx.serialization.json.Json
|
||||||
import kotlinx.serialization.json.JsonElement
|
import kotlinx.serialization.json.JsonElement
|
||||||
@ -75,6 +77,18 @@ public class VisionManager(meta: Meta) : AbstractPlugin(meta) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public abstract class VisionPlugin(meta: Meta = Meta.EMPTY) : AbstractPlugin(meta) {
|
||||||
|
public val visionManager: VisionManager by require(VisionManager)
|
||||||
|
|
||||||
|
protected abstract val visionSerializersModule: SerializersModule
|
||||||
|
|
||||||
|
override fun content(target: String): Map<Name, Any> = when (target) {
|
||||||
|
VisionManager.VISION_SERIALIZER_MODULE_TARGET -> mapOf(tag.toString().toName() to visionSerializersModule)
|
||||||
|
else -> super.content(target)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fetch a [VisionManager] from this plugin
|
* Fetch a [VisionManager] from this plugin
|
||||||
*/
|
*/
|
||||||
|
@ -0,0 +1,26 @@
|
|||||||
|
package hep.dataforge.vision.html
|
||||||
|
|
||||||
|
import hep.dataforge.context.Context
|
||||||
|
import kotlinx.html.*
|
||||||
|
|
||||||
|
public data class Page(
|
||||||
|
public val context: Context,
|
||||||
|
public val title: String,
|
||||||
|
public val headers: Map<String, HtmlFragment>,
|
||||||
|
public val content: HtmlVisionFragment
|
||||||
|
) {
|
||||||
|
public fun <R> render(root: TagConsumer<R>): R = root.apply {
|
||||||
|
head {
|
||||||
|
meta {
|
||||||
|
charset = "utf-8"
|
||||||
|
headers.values.forEach {
|
||||||
|
fragment(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
title(title)
|
||||||
|
}
|
||||||
|
body {
|
||||||
|
embedVisionFragment(context.visionManager, fragment = content)
|
||||||
|
}
|
||||||
|
}.finalize()
|
||||||
|
}
|
@ -4,19 +4,18 @@ import hep.dataforge.meta.Meta
|
|||||||
import hep.dataforge.names.Name
|
import hep.dataforge.names.Name
|
||||||
import hep.dataforge.vision.Vision
|
import hep.dataforge.vision.Vision
|
||||||
import hep.dataforge.vision.VisionManager
|
import hep.dataforge.vision.VisionManager
|
||||||
import kotlinx.html.DIV
|
import kotlinx.html.*
|
||||||
import kotlinx.html.FlowContent
|
|
||||||
import kotlinx.html.script
|
|
||||||
import kotlinx.html.unsafe
|
|
||||||
|
|
||||||
|
|
||||||
public fun FlowContent.embedVisionFragment(
|
public fun TagConsumer<*>.embedVisionFragment(
|
||||||
manager: VisionManager,
|
manager: VisionManager,
|
||||||
idPrefix: String? = null,
|
idPrefix: String? = null,
|
||||||
fragment: HtmlVisionFragment,
|
fragment: HtmlVisionFragment,
|
||||||
) {
|
): Map<Name, Vision> {
|
||||||
val consumer = object : VisionTagConsumer<Any?>(consumer, idPrefix) {
|
val visionMap = HashMap<Name, Vision>()
|
||||||
|
val consumer = object : VisionTagConsumer<Any?>(this@embedVisionFragment, idPrefix) {
|
||||||
override fun DIV.renderVision(name: Name, vision: Vision, outputMeta: Meta) {
|
override fun DIV.renderVision(name: Name, vision: Vision, outputMeta: Meta) {
|
||||||
|
visionMap[name] = vision
|
||||||
script {
|
script {
|
||||||
type = "text/json"
|
type = "text/json"
|
||||||
attributes["class"] = OUTPUT_DATA_CLASS
|
attributes["class"] = OUTPUT_DATA_CLASS
|
||||||
@ -27,17 +26,29 @@ public fun FlowContent.embedVisionFragment(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
fragment(consumer)
|
fragment(consumer)
|
||||||
|
return visionMap
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public fun FlowContent.embedVisionFragment(
|
||||||
|
manager: VisionManager,
|
||||||
|
idPrefix: String? = null,
|
||||||
|
fragment: HtmlVisionFragment,
|
||||||
|
): Map<Name, Vision> = consumer.embedVisionFragment(manager, idPrefix, fragment)
|
||||||
|
|
||||||
public typealias HtmlVisionRenderer = FlowContent.(name: Name, vision: Vision, meta: Meta) -> Unit
|
public typealias HtmlVisionRenderer = FlowContent.(name: Name, vision: Vision, meta: Meta) -> Unit
|
||||||
|
|
||||||
public fun <R> FlowContent.renderVisionFragment(
|
public fun FlowContent.renderVisionFragment(
|
||||||
renderer: DIV.(name: Name, vision: Vision, meta: Meta) -> Unit,
|
renderer: DIV.(name: Name, vision: Vision, meta: Meta) -> Unit,
|
||||||
idPrefix: String? = null,
|
idPrefix: String? = null,
|
||||||
fragment: HtmlVisionFragment,
|
fragment: HtmlVisionFragment,
|
||||||
) {
|
): Map<Name, Vision> {
|
||||||
|
val visionMap = HashMap<Name, Vision>()
|
||||||
val consumer = object : VisionTagConsumer<Any?>(consumer, idPrefix) {
|
val consumer = object : VisionTagConsumer<Any?>(consumer, idPrefix) {
|
||||||
override fun DIV.renderVision(name: Name, vision: Vision, outputMeta: Meta) = renderer(name, vision, outputMeta)
|
override fun DIV.renderVision(name: Name, vision: Vision, outputMeta: Meta) {
|
||||||
|
visionMap[name] = vision
|
||||||
|
renderer(name, vision, outputMeta)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
fragment(consumer)
|
fragment(consumer)
|
||||||
|
return visionMap
|
||||||
}
|
}
|
@ -1,16 +0,0 @@
|
|||||||
package hep.dataforge.vision.layout
|
|
||||||
|
|
||||||
import hep.dataforge.meta.Meta
|
|
||||||
import hep.dataforge.names.Name
|
|
||||||
import hep.dataforge.vision.Vision
|
|
||||||
|
|
||||||
public fun interface Output<in V : Vision> {
|
|
||||||
public fun render(vision: V)
|
|
||||||
}
|
|
||||||
|
|
||||||
public interface Page<in V : Vision> {
|
|
||||||
public fun output(name: Name, meta: Meta = Meta.EMPTY): Output<V>?
|
|
||||||
}
|
|
||||||
|
|
||||||
public fun <V : Vision> Page<V>.render(name: Name, vision: V): Unit =
|
|
||||||
output(name)?.render(vision) ?: error("Could not resolve renderer for name $name")
|
|
@ -3,7 +3,6 @@ package hep.dataforge.vision.html
|
|||||||
import hep.dataforge.meta.DFExperimental
|
import hep.dataforge.meta.DFExperimental
|
||||||
import hep.dataforge.meta.set
|
import hep.dataforge.meta.set
|
||||||
import hep.dataforge.vision.VisionBase
|
import hep.dataforge.vision.VisionBase
|
||||||
import hep.dataforge.vision.configure
|
|
||||||
import kotlinx.html.*
|
import kotlinx.html.*
|
||||||
import kotlinx.html.stream.createHTML
|
import kotlinx.html.stream.createHTML
|
||||||
import kotlin.test.Test
|
import kotlin.test.Test
|
||||||
@ -54,7 +53,7 @@ class HtmlTagTest {
|
|||||||
fun testStringRender() {
|
fun testStringRender() {
|
||||||
println(
|
println(
|
||||||
createHTML().div {
|
createHTML().div {
|
||||||
renderVisionFragment<String>(simpleVisionRenderer, fragment = fragment)
|
renderVisionFragment(simpleVisionRenderer, fragment = fragment)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
package hep.dataforge
|
package hep.dataforge.vision
|
||||||
|
|
||||||
import kotlinx.browser.document
|
import kotlinx.browser.document
|
||||||
import kotlinx.dom.hasClass
|
import kotlinx.dom.hasClass
|
@ -0,0 +1,22 @@
|
|||||||
|
package hep.dataforge.vision
|
||||||
|
|
||||||
|
import hep.dataforge.context.Context
|
||||||
|
import hep.dataforge.context.Global
|
||||||
|
import hep.dataforge.vision.client.VisionClient
|
||||||
|
import hep.dataforge.vision.client.renderAllVisions
|
||||||
|
import kotlinx.browser.window
|
||||||
|
|
||||||
|
public actual val VisionForge: Context = Global.context("VisionForge").apply{
|
||||||
|
plugins.fetch(VisionManager)
|
||||||
|
plugins.fetch(VisionClient)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Render all visions in this [window] using current global state of [VisionForge]
|
||||||
|
*/
|
||||||
|
@JsExport
|
||||||
|
public fun renderVisionsInWindow(){
|
||||||
|
window.onload = {
|
||||||
|
VisionForge.plugins[VisionClient]?.renderAllVisions()
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,8 @@
|
|||||||
|
package hep.dataforge.vision
|
||||||
|
|
||||||
|
import hep.dataforge.context.Context
|
||||||
|
import hep.dataforge.context.Global
|
||||||
|
|
||||||
|
public actual val VisionForge: Context = Global.context("VisionForge").apply{
|
||||||
|
plugins.fetch(VisionManager)
|
||||||
|
}
|
@ -1,8 +1,7 @@
|
|||||||
package hep.dataforge.vision
|
package hep.dataforge.vision.html
|
||||||
|
|
||||||
import hep.dataforge.context.Context
|
|
||||||
import hep.dataforge.meta.DFExperimental
|
import hep.dataforge.meta.DFExperimental
|
||||||
import hep.dataforge.vision.html.HtmlFragment
|
import hep.dataforge.vision.VisionManager
|
||||||
import kotlinx.html.link
|
import kotlinx.html.link
|
||||||
import kotlinx.html.script
|
import kotlinx.html.script
|
||||||
import kotlinx.html.unsafe
|
import kotlinx.html.unsafe
|
||||||
@ -100,14 +99,14 @@ internal fun fileCssHeader(
|
|||||||
* Make a script header, automatically copying file to appropriate location
|
* Make a script header, automatically copying file to appropriate location
|
||||||
*/
|
*/
|
||||||
@DFExperimental
|
@DFExperimental
|
||||||
public fun Context.scriptHeader(
|
public fun scriptHeader(
|
||||||
scriptResource: String,
|
scriptResource: String,
|
||||||
htmlPath: Path,
|
htmlPath: Path?,
|
||||||
resourceLocation: ResourceLocation,
|
resourceLocation: ResourceLocation,
|
||||||
): HtmlFragment {
|
): HtmlFragment {
|
||||||
val targetPath = when (resourceLocation) {
|
val targetPath = when (resourceLocation) {
|
||||||
ResourceLocation.LOCAL -> checkOrStoreFile(
|
ResourceLocation.LOCAL -> checkOrStoreFile(
|
||||||
htmlPath,
|
htmlPath ?: Path.of("."),
|
||||||
Path.of(VISIONFORGE_ASSETS_PATH),
|
Path.of(VISIONFORGE_ASSETS_PATH),
|
||||||
scriptResource
|
scriptResource
|
||||||
)
|
)
|
@ -0,0 +1,89 @@
|
|||||||
|
package hep.dataforge.vision
|
||||||
|
|
||||||
|
import hep.dataforge.context.Context
|
||||||
|
import hep.dataforge.meta.DFExperimental
|
||||||
|
import hep.dataforge.vision.html.HtmlFragment
|
||||||
|
import hep.dataforge.vision.html.HtmlVisionFragment
|
||||||
|
import hep.dataforge.vision.html.Page
|
||||||
|
import kotlinx.html.stream.createHTML
|
||||||
|
import java.awt.Desktop
|
||||||
|
import java.nio.file.Files
|
||||||
|
import java.nio.file.Path
|
||||||
|
|
||||||
|
//
|
||||||
|
///**
|
||||||
|
// * Create a full html string (including the head) for a given [HtmlVisionFragment]
|
||||||
|
// */
|
||||||
|
//@DFExperimental
|
||||||
|
//public fun Context.makeVisionString(
|
||||||
|
// fragment: HtmlVisionFragment,
|
||||||
|
// title: String = "VisionForge page",
|
||||||
|
// headerBuilder: () -> HtmlFragment,
|
||||||
|
//): String = createHTML().apply {
|
||||||
|
// head {
|
||||||
|
// meta {
|
||||||
|
// charset = "utf-8"
|
||||||
|
// fragment(headerBuilder())
|
||||||
|
// }
|
||||||
|
// title(title)
|
||||||
|
// }
|
||||||
|
// body {
|
||||||
|
// embedVisionFragment(visionManager, fragment = fragment)
|
||||||
|
// }
|
||||||
|
//}.finalize()
|
||||||
|
//
|
||||||
|
//
|
||||||
|
///**
|
||||||
|
// * Make a file with the embedded vision data
|
||||||
|
// */
|
||||||
|
//@DFExperimental
|
||||||
|
//public fun Context.makeVisionFile(
|
||||||
|
// fragment: HtmlVisionFragment,
|
||||||
|
// path: Path? = null,
|
||||||
|
// title: String = "VisionForge page",
|
||||||
|
// show: Boolean = true,
|
||||||
|
// headerBuilder: (Path) -> HtmlFragment,
|
||||||
|
//) {
|
||||||
|
// val actualFile = path?.let {
|
||||||
|
// Path.of(System.getProperty("user.home")).resolve(path)
|
||||||
|
// } ?: Files.createTempFile("tempPlot", ".html")
|
||||||
|
// //Files.createDirectories(actualFile.parent)
|
||||||
|
// val htmlString = makeVisionString(fragment, title) { headerBuilder(actualFile) }
|
||||||
|
//
|
||||||
|
// Files.writeString(actualFile, htmlString)
|
||||||
|
// if (show) {
|
||||||
|
// Desktop.getDesktop().browse(actualFile.toFile().toURI())
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
|
||||||
|
@DFExperimental
|
||||||
|
public fun Context.page(
|
||||||
|
title: String,
|
||||||
|
content: HtmlVisionFragment,
|
||||||
|
vararg headers: Pair<String, HtmlFragment>,
|
||||||
|
): Page = Page(this, title, mapOf(*headers), content)
|
||||||
|
|
||||||
|
|
||||||
|
@DFExperimental
|
||||||
|
public fun Page.makeFile(
|
||||||
|
path: Path?,
|
||||||
|
defaultHeaders: ((Path) -> Map<String,HtmlFragment>)? = null,
|
||||||
|
): Path {
|
||||||
|
val actualFile = path?.let {
|
||||||
|
Path.of(System.getProperty("user.home")).resolve(path)
|
||||||
|
} ?: Files.createTempFile("tempPlot", ".html")
|
||||||
|
|
||||||
|
val actualDefaultHeaders = defaultHeaders?.invoke(actualFile)
|
||||||
|
val actualPage = if(actualDefaultHeaders == null) this else copy(headers = actualDefaultHeaders + headers)
|
||||||
|
|
||||||
|
val htmlString = actualPage.render(createHTML())
|
||||||
|
|
||||||
|
Files.writeString(actualFile, htmlString)
|
||||||
|
return actualFile
|
||||||
|
}
|
||||||
|
|
||||||
|
@DFExperimental
|
||||||
|
public fun Page.show(path: Path? = null) {
|
||||||
|
val actualPath = makeFile(path)
|
||||||
|
Desktop.getDesktop().browse(actualPath.toFile().toURI())
|
||||||
|
}
|
@ -1,51 +0,0 @@
|
|||||||
package hep.dataforge.vision
|
|
||||||
|
|
||||||
import hep.dataforge.context.Context
|
|
||||||
import hep.dataforge.meta.DFExperimental
|
|
||||||
import hep.dataforge.vision.html.HtmlFragment
|
|
||||||
import hep.dataforge.vision.html.HtmlVisionFragment
|
|
||||||
import hep.dataforge.vision.html.embedVisionFragment
|
|
||||||
import hep.dataforge.vision.html.fragment
|
|
||||||
import kotlinx.html.body
|
|
||||||
import kotlinx.html.head
|
|
||||||
import kotlinx.html.meta
|
|
||||||
import kotlinx.html.stream.createHTML
|
|
||||||
import kotlinx.html.title
|
|
||||||
import java.awt.Desktop
|
|
||||||
import java.nio.file.Files
|
|
||||||
import java.nio.file.Path
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Make a file with the embedded vision data
|
|
||||||
*/
|
|
||||||
@DFExperimental
|
|
||||||
public fun Context.makeVisionFile(
|
|
||||||
fragment: HtmlVisionFragment,
|
|
||||||
path: Path? = null,
|
|
||||||
title: String = "VisionForge page",
|
|
||||||
show: Boolean = true,
|
|
||||||
headerBuilder: (Path) -> HtmlFragment,
|
|
||||||
) {
|
|
||||||
val actualFile = path?.let {
|
|
||||||
Path.of(System.getProperty("user.home")).resolve(path)
|
|
||||||
} ?: Files.createTempFile("tempPlot", ".html")
|
|
||||||
//Files.createDirectories(actualFile.parent)
|
|
||||||
val htmlString = createHTML().apply {
|
|
||||||
head {
|
|
||||||
meta {
|
|
||||||
charset = "utf-8"
|
|
||||||
fragment(headerBuilder(actualFile))
|
|
||||||
}
|
|
||||||
title(title)
|
|
||||||
}
|
|
||||||
body {
|
|
||||||
embedVisionFragment(visionManager, fragment = fragment)
|
|
||||||
}
|
|
||||||
}.finalize()
|
|
||||||
|
|
||||||
Files.writeString(actualFile, htmlString)
|
|
||||||
if (show) {
|
|
||||||
Desktop.getDesktop().browse(actualFile.toFile().toURI())
|
|
||||||
}
|
|
||||||
}
|
|
@ -2,7 +2,6 @@ package hep.dataforge.vision.solid
|
|||||||
|
|
||||||
import hep.dataforge.context.Context
|
import hep.dataforge.context.Context
|
||||||
import hep.dataforge.context.ContextAware
|
import hep.dataforge.context.ContextAware
|
||||||
import hep.dataforge.vision.layout.Output
|
|
||||||
import hep.dataforge.vision.solid.specifications.Canvas3DOptions
|
import hep.dataforge.vision.solid.specifications.Canvas3DOptions
|
||||||
import javafx.application.Platform
|
import javafx.application.Platform
|
||||||
import javafx.beans.property.ObjectProperty
|
import javafx.beans.property.ObjectProperty
|
||||||
@ -12,8 +11,10 @@ import javafx.scene.paint.Color
|
|||||||
import org.fxyz3d.scene.Axes
|
import org.fxyz3d.scene.Axes
|
||||||
import tornadofx.*
|
import tornadofx.*
|
||||||
|
|
||||||
class FXCanvas3D(val plugin: FX3DPlugin, val spec: Canvas3DOptions = Canvas3DOptions.empty()) :
|
class FXCanvas3D(
|
||||||
Fragment(), Output<Solid>, ContextAware {
|
val plugin: FX3DPlugin,
|
||||||
|
val spec: Canvas3DOptions = Canvas3DOptions.empty(),
|
||||||
|
) : Fragment(), ContextAware {
|
||||||
|
|
||||||
override val context: Context get() = plugin.context
|
override val context: Context get() = plugin.context
|
||||||
|
|
||||||
@ -78,7 +79,7 @@ class FXCanvas3D(val plugin: FX3DPlugin, val spec: Canvas3DOptions = Canvas3DOpt
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun render(vision: Solid) {
|
fun render(vision: Solid) {
|
||||||
rootObject = vision
|
rootObject = vision
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -9,6 +9,27 @@ kscience {
|
|||||||
val plotlyVersion = "0.3.1-dev"
|
val plotlyVersion = "0.3.1-dev"
|
||||||
|
|
||||||
kotlin {
|
kotlin {
|
||||||
|
js{
|
||||||
|
//binaries.library()
|
||||||
|
binaries.executable()
|
||||||
|
browser {
|
||||||
|
webpackTask {
|
||||||
|
this.outputFileName = "js/visionforge-three.js"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
afterEvaluate {
|
||||||
|
val jsBrowserDistribution by tasks.getting
|
||||||
|
|
||||||
|
tasks.getByName<ProcessResources>("jvmProcessResources") {
|
||||||
|
dependsOn(jsBrowserDistribution)
|
||||||
|
afterEvaluate {
|
||||||
|
from(jsBrowserDistribution)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
sourceSets {
|
sourceSets {
|
||||||
commonMain {
|
commonMain {
|
||||||
dependencies {
|
dependencies {
|
||||||
|
@ -1,12 +1,16 @@
|
|||||||
package hep.dataforge.vision.plotly
|
package hep.dataforge.vision.plotly
|
||||||
|
|
||||||
|
import hep.dataforge.meta.Config
|
||||||
import hep.dataforge.meta.DFExperimental
|
import hep.dataforge.meta.DFExperimental
|
||||||
import hep.dataforge.vision.VisionBase
|
import hep.dataforge.vision.VisionBase
|
||||||
import hep.dataforge.vision.html.VisionOutput
|
import hep.dataforge.vision.html.VisionOutput
|
||||||
import kscience.plotly.Plot
|
import kscience.plotly.Plot
|
||||||
import kscience.plotly.Plotly
|
import kscience.plotly.Plotly
|
||||||
|
|
||||||
public class VisionOfPlotly(public val plot: Plot): VisionBase(plot.config)
|
@Serializable
|
||||||
|
public class VisionOfPlotly(private val plotConfig: Config) : VisionBase(plotConfig){
|
||||||
|
public val plot: Plot get() = Plot(plotConfig)
|
||||||
|
}
|
||||||
|
|
||||||
@DFExperimental
|
@DFExperimental
|
||||||
public inline fun VisionOutput.plotly(block: Plot.() -> Unit): VisionOfPlotly = VisionOfPlotly(Plotly.plot(block))
|
public inline fun VisionOutput.plotly(block: Plot.() -> Unit): VisionOfPlotly = VisionOfPlotly(Plotly.plot(block).config)
|
@ -0,0 +1,15 @@
|
|||||||
|
package hep.dataforge.vision.plotly
|
||||||
|
|
||||||
|
import hep.dataforge.vision.Vision
|
||||||
|
import hep.dataforge.vision.VisionPlugin
|
||||||
|
import kotlinx.serialization.modules.SerializersModule
|
||||||
|
import kotlinx.serialization.modules.polymorphic
|
||||||
|
import kotlinx.serialization.modules.subclass
|
||||||
|
|
||||||
|
public expect class PlotlyPlugin : VisionPlugin
|
||||||
|
|
||||||
|
internal val plotlySerializersModule = SerializersModule {
|
||||||
|
polymorphic(Vision::class) {
|
||||||
|
subclass(VisionOfPlotly.serializer())
|
||||||
|
}
|
||||||
|
}
|
@ -1,15 +0,0 @@
|
|||||||
package hep.dataforge.vision.plotly
|
|
||||||
|
|
||||||
//public fun main() {
|
|
||||||
// val visionContext: Context = Global.context("vision-client")
|
|
||||||
//
|
|
||||||
// //Loading three-js renderer
|
|
||||||
// val threePlugin = visionContext.plugins.fetch(PlotlyPlugin)
|
|
||||||
//
|
|
||||||
// val clientManager = visionContext.plugins.fetch(VisionClient)
|
|
||||||
//
|
|
||||||
// //Fetch from server and render visions for all outputs
|
|
||||||
// window.onload = {
|
|
||||||
// clientManager.renderAllVisions()
|
|
||||||
// }
|
|
||||||
//}
|
|
@ -1,23 +1,29 @@
|
|||||||
package hep.dataforge.vision.plotly
|
package hep.dataforge.vision.plotly
|
||||||
|
|
||||||
import hep.dataforge.context.AbstractPlugin
|
import hep.dataforge.context.*
|
||||||
import hep.dataforge.context.Context
|
|
||||||
import hep.dataforge.context.PluginFactory
|
|
||||||
import hep.dataforge.context.PluginTag
|
|
||||||
import hep.dataforge.meta.Meta
|
import hep.dataforge.meta.Meta
|
||||||
import hep.dataforge.vision.Vision
|
import hep.dataforge.vision.Vision
|
||||||
|
import hep.dataforge.vision.VisionForge
|
||||||
|
import hep.dataforge.vision.VisionPlugin
|
||||||
import hep.dataforge.vision.client.ElementVisionRenderer
|
import hep.dataforge.vision.client.ElementVisionRenderer
|
||||||
|
import hep.dataforge.vision.client.VisionClient
|
||||||
|
import kotlinx.serialization.modules.SerializersModule
|
||||||
import kscience.plotly.PlotlyConfig
|
import kscience.plotly.PlotlyConfig
|
||||||
import kscience.plotly.plot
|
import kscience.plotly.plot
|
||||||
import org.w3c.dom.Element
|
import org.w3c.dom.Element
|
||||||
import kotlin.reflect.KClass
|
import kotlin.reflect.KClass
|
||||||
|
|
||||||
public class PlotlyPlugin : AbstractPlugin(), ElementVisionRenderer {
|
public actual class PlotlyPlugin : VisionPlugin(), ElementVisionRenderer {
|
||||||
|
public val visionClient: VisionClient by require(VisionClient)
|
||||||
|
|
||||||
override val tag: PluginTag get() = Companion.tag
|
override val tag: PluginTag get() = Companion.tag
|
||||||
|
|
||||||
override fun rateVision(vision: Vision): Int =
|
override val visionSerializersModule: SerializersModule get() = plotlySerializersModule
|
||||||
if (vision is VisionOfPlotly) ElementVisionRenderer.DEFAULT_RATING else ElementVisionRenderer.ZERO_RATING
|
|
||||||
|
override fun rateVision(vision: Vision): Int = when (vision) {
|
||||||
|
is VisionOfPlotly -> ElementVisionRenderer.DEFAULT_RATING
|
||||||
|
else -> ElementVisionRenderer.ZERO_RATING
|
||||||
|
}
|
||||||
|
|
||||||
override fun render(element: Element, vision: Vision, meta: Meta) {
|
override fun render(element: Element, vision: Vision, meta: Meta) {
|
||||||
val plot = (vision as? VisionOfPlotly)?.plot ?: error("Only VisionOfPlotly visions are supported")
|
val plot = (vision as? VisionOfPlotly)?.plot ?: error("Only VisionOfPlotly visions are supported")
|
||||||
@ -31,3 +37,11 @@ public class PlotlyPlugin : AbstractPlugin(), ElementVisionRenderer {
|
|||||||
override fun invoke(meta: Meta, context: Context): PlotlyPlugin = PlotlyPlugin()
|
override fun invoke(meta: Meta, context: Context): PlotlyPlugin = PlotlyPlugin()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ensure that [PlotlyPlugin] is loaded in the global [VisionForge] context
|
||||||
|
*/
|
||||||
|
@JsExport
|
||||||
|
public fun withPlotly() {
|
||||||
|
VisionForge.plugins.fetch(PlotlyPlugin)
|
||||||
|
}
|
@ -0,0 +1,30 @@
|
|||||||
|
package hep.dataforge.vision.plotly
|
||||||
|
|
||||||
|
import hep.dataforge.meta.DFExperimental
|
||||||
|
import hep.dataforge.vision.html.HtmlFragment
|
||||||
|
import hep.dataforge.vision.html.ResourceLocation
|
||||||
|
import hep.dataforge.vision.html.scriptHeader
|
||||||
|
import kotlinx.html.script
|
||||||
|
import kotlinx.html.unsafe
|
||||||
|
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,
|
||||||
|
filePath,
|
||||||
|
resourceLocation = location
|
||||||
|
).invoke(this)
|
||||||
|
script {
|
||||||
|
type = "text/javascript"
|
||||||
|
unsafe {
|
||||||
|
//language=JavaScript
|
||||||
|
+"hep.dataforge.vision.plotly.loadPlotly()"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,27 @@
|
|||||||
|
package hep.dataforge.vision.plotly
|
||||||
|
|
||||||
|
import hep.dataforge.context.Context
|
||||||
|
import hep.dataforge.context.Plugin
|
||||||
|
import hep.dataforge.context.PluginFactory
|
||||||
|
import hep.dataforge.context.PluginTag
|
||||||
|
import hep.dataforge.meta.Meta
|
||||||
|
import hep.dataforge.vision.VisionPlugin
|
||||||
|
import kotlinx.serialization.modules.SerializersModule
|
||||||
|
import kotlin.reflect.KClass
|
||||||
|
|
||||||
|
public actual class PlotlyPlugin : VisionPlugin(), Plugin {
|
||||||
|
|
||||||
|
override val tag: PluginTag get() = Companion.tag
|
||||||
|
|
||||||
|
override val visionSerializersModule: SerializersModule get() = plotlySerializersModule
|
||||||
|
|
||||||
|
public companion object : PluginFactory<PlotlyPlugin> {
|
||||||
|
override val tag: PluginTag = PluginTag("vision.plotly", PluginTag.DATAFORGE_GROUP)
|
||||||
|
override val type: KClass<PlotlyPlugin> = PlotlyPlugin::class
|
||||||
|
override fun invoke(meta: Meta, context: Context): PlotlyPlugin = PlotlyPlugin()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public fun Context.withPlotly(): Context = apply {
|
||||||
|
plugins.fetch(PlotlyPlugin)
|
||||||
|
}
|
@ -11,7 +11,6 @@ import hep.dataforge.values.ValueType
|
|||||||
import hep.dataforge.values.asValue
|
import hep.dataforge.values.asValue
|
||||||
import hep.dataforge.vision.*
|
import hep.dataforge.vision.*
|
||||||
import hep.dataforge.vision.Vision.Companion.VISIBLE_KEY
|
import hep.dataforge.vision.Vision.Companion.VISIBLE_KEY
|
||||||
import hep.dataforge.vision.layout.Output
|
|
||||||
import hep.dataforge.vision.solid.Solid.Companion.DETAIL_KEY
|
import hep.dataforge.vision.solid.Solid.Companion.DETAIL_KEY
|
||||||
import hep.dataforge.vision.solid.Solid.Companion.IGNORE_KEY
|
import hep.dataforge.vision.solid.Solid.Companion.IGNORE_KEY
|
||||||
import hep.dataforge.vision.solid.Solid.Companion.LAYER_KEY
|
import hep.dataforge.vision.solid.Solid.Companion.LAYER_KEY
|
||||||
@ -108,9 +107,6 @@ public var Solid.layer: Int
|
|||||||
setProperty(LAYER_KEY, value)
|
setProperty(LAYER_KEY, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
@VisionBuilder
|
|
||||||
public fun Output<Solid>.solidGroup(builder: SolidGroup.() -> Unit): Unit = render(SolidGroup().apply(builder))
|
|
||||||
|
|
||||||
// Common properties
|
// Common properties
|
||||||
|
|
||||||
public enum class RotationOrder {
|
public enum class RotationOrder {
|
||||||
|
@ -1,18 +1,11 @@
|
|||||||
package hep.dataforge.vision.solid
|
package hep.dataforge.vision.solid
|
||||||
|
|
||||||
import hep.dataforge.context.AbstractPlugin
|
|
||||||
import hep.dataforge.context.Context
|
import hep.dataforge.context.Context
|
||||||
import hep.dataforge.context.PluginFactory
|
import hep.dataforge.context.PluginFactory
|
||||||
import hep.dataforge.context.PluginTag
|
import hep.dataforge.context.PluginTag
|
||||||
import hep.dataforge.meta.DFExperimental
|
import hep.dataforge.meta.DFExperimental
|
||||||
import hep.dataforge.meta.Meta
|
import hep.dataforge.meta.Meta
|
||||||
import hep.dataforge.names.Name
|
import hep.dataforge.vision.*
|
||||||
import hep.dataforge.names.toName
|
|
||||||
import hep.dataforge.vision.Vision
|
|
||||||
import hep.dataforge.vision.VisionBase
|
|
||||||
import hep.dataforge.vision.VisionGroupBase
|
|
||||||
import hep.dataforge.vision.VisionManager
|
|
||||||
import hep.dataforge.vision.VisionManager.Companion.VISION_SERIALIZER_MODULE_TARGET
|
|
||||||
import hep.dataforge.vision.html.VisionOutput
|
import hep.dataforge.vision.html.VisionOutput
|
||||||
import kotlinx.serialization.PolymorphicSerializer
|
import kotlinx.serialization.PolymorphicSerializer
|
||||||
import kotlinx.serialization.json.Json
|
import kotlinx.serialization.json.Json
|
||||||
@ -23,16 +16,11 @@ import kotlinx.serialization.modules.subclass
|
|||||||
import kotlin.reflect.KClass
|
import kotlin.reflect.KClass
|
||||||
|
|
||||||
|
|
||||||
public class SolidManager(meta: Meta) : AbstractPlugin(meta) {
|
public class SolidManager(meta: Meta) : VisionPlugin(meta) {
|
||||||
|
|
||||||
public val visionManager: VisionManager by require(VisionManager)
|
|
||||||
|
|
||||||
override val tag: PluginTag get() = Companion.tag
|
override val tag: PluginTag get() = Companion.tag
|
||||||
|
|
||||||
override fun content(target: String): Map<Name, Any> = when (target) {
|
override val visionSerializersModule: SerializersModule get() = serializersModuleForSolids
|
||||||
VISION_SERIALIZER_MODULE_TARGET -> mapOf(tag.name.toName() to serializersModuleForSolids)
|
|
||||||
else -> super.content(target)
|
|
||||||
}
|
|
||||||
|
|
||||||
public companion object : PluginFactory<SolidManager> {
|
public companion object : PluginFactory<SolidManager> {
|
||||||
override val tag: PluginTag = PluginTag(name = "vision.solid", group = PluginTag.DATAFORGE_GROUP)
|
override val tag: PluginTag = PluginTag(name = "vision.solid", group = PluginTag.DATAFORGE_GROUP)
|
||||||
@ -66,15 +54,18 @@ public class SolidManager(meta: Meta) : AbstractPlugin(meta) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal val jsonForSolids: Json = Json(VisionManager.defaultJson){
|
internal val jsonForSolids: Json = Json(VisionManager.defaultJson) {
|
||||||
serializersModule = serializersModuleForSolids
|
serializersModule = serializersModuleForSolids
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun encodeToString(solid: Solid): String = jsonForSolids.encodeToString(PolymorphicSerializer(Vision::class), solid)
|
public fun encodeToString(solid: Solid): String =
|
||||||
|
jsonForSolids.encodeToString(PolymorphicSerializer(Vision::class), solid)
|
||||||
|
|
||||||
public fun decodeFromString(str: String): Solid = jsonForSolids.decodeFromString(PolymorphicSerializer(Solid::class), str)
|
public fun decodeFromString(str: String): Solid =
|
||||||
|
jsonForSolids.decodeFromString(PolymorphicSerializer(Solid::class), str)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@VisionBuilder
|
||||||
@DFExperimental
|
@DFExperimental
|
||||||
public inline fun VisionOutput.solid(block: SolidGroup.() -> Unit): SolidGroup = SolidGroup().apply(block)
|
public inline fun VisionOutput.solid(block: SolidGroup.() -> Unit): SolidGroup = SolidGroup().apply(block)
|
@ -4,16 +4,14 @@ import hep.dataforge.meta.Meta
|
|||||||
import hep.dataforge.meta.MetaBuilder
|
import hep.dataforge.meta.MetaBuilder
|
||||||
import hep.dataforge.meta.double
|
import hep.dataforge.meta.double
|
||||||
import hep.dataforge.meta.get
|
import hep.dataforge.meta.get
|
||||||
import kotlinx.serialization.Serializable
|
|
||||||
import kotlin.math.PI
|
import kotlin.math.PI
|
||||||
|
|
||||||
public const val PI2: Float = 2 * PI.toFloat()
|
public const val PI2: Float = 2 * PI.toFloat()
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
public data class Point2D(public var x: Double, public var y: Double){
|
public data class Point2D(public var x: Double, public var y: Double)
|
||||||
public constructor(x: Number, y: Number) : this(x.toDouble(), y.toDouble())
|
|
||||||
}
|
|
||||||
|
|
||||||
|
public fun Point2D(x: Number, y: Number): Point2D = Point2D(x.toDouble(), y.toDouble())
|
||||||
|
|
||||||
public fun Point2D.toMeta(): Meta = Meta {
|
public fun Point2D.toMeta(): Meta = Meta {
|
||||||
Solid.X_KEY put x
|
Solid.X_KEY put x
|
||||||
@ -28,14 +26,14 @@ public data class Point3D(
|
|||||||
public var y: Double,
|
public var y: Double,
|
||||||
public var z: Double,
|
public var z: Double,
|
||||||
) {
|
) {
|
||||||
public constructor(x: Number, y: Number, z: Number) : this(x.toDouble(), y.toDouble(), z.toDouble())
|
public companion object {
|
||||||
|
|
||||||
public companion object{
|
|
||||||
public val ZERO: Point3D = Point3D(0.0, 0.0, 0.0)
|
public val ZERO: Point3D = Point3D(0.0, 0.0, 0.0)
|
||||||
public val ONE: Point3D = Point3D(1.0, 1.0, 1.0)
|
public val ONE: Point3D = Point3D(1.0, 1.0, 1.0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public fun Point3D(x: Number, y: Number, z: Number): Point3D = Point3D(x.toDouble(), y.toDouble(), z.toDouble())
|
||||||
|
|
||||||
public operator fun Point3D.plus(other: Point3D): Point3D = Point3D(
|
public operator fun Point3D.plus(other: Point3D): Point3D = Point3D(
|
||||||
this.x + other.x,
|
this.x + other.x,
|
||||||
this.y + other.y,
|
this.y + other.y,
|
||||||
|
@ -6,6 +6,12 @@ kscience {
|
|||||||
useSerialization()
|
useSerialization()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
kotlin{
|
||||||
|
js{
|
||||||
|
binaries.library()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
api(project(":visionforge-solid"))
|
api(project(":visionforge-solid"))
|
||||||
implementation(npm("three", "0.122.0"))
|
implementation(npm("three", "0.122.0"))
|
||||||
|
@ -1,12 +1,9 @@
|
|||||||
package hep.dataforge.vision.solid.three
|
package hep.dataforge.vision.solid.three
|
||||||
|
|
||||||
import hep.dataforge.meta.get
|
|
||||||
import hep.dataforge.meta.string
|
|
||||||
import hep.dataforge.names.Name
|
import hep.dataforge.names.Name
|
||||||
import hep.dataforge.names.plus
|
import hep.dataforge.names.plus
|
||||||
import hep.dataforge.names.toName
|
import hep.dataforge.names.toName
|
||||||
import hep.dataforge.vision.Colors
|
import hep.dataforge.vision.Colors
|
||||||
import hep.dataforge.vision.layout.Output
|
|
||||||
import hep.dataforge.vision.solid.Solid
|
import hep.dataforge.vision.solid.Solid
|
||||||
import hep.dataforge.vision.solid.specifications.*
|
import hep.dataforge.vision.solid.specifications.*
|
||||||
import hep.dataforge.vision.solid.three.ThreeMaterials.HIGHLIGHT_MATERIAL
|
import hep.dataforge.vision.solid.three.ThreeMaterials.HIGHLIGHT_MATERIAL
|
||||||
@ -39,7 +36,7 @@ import kotlin.math.sin
|
|||||||
public class ThreeCanvas(
|
public class ThreeCanvas(
|
||||||
public val three: ThreePlugin,
|
public val three: ThreePlugin,
|
||||||
public val options: Canvas3DOptions,
|
public val options: Canvas3DOptions,
|
||||||
) : Output<Solid> {
|
) {
|
||||||
private var root: Object3D? = null
|
private var root: Object3D? = null
|
||||||
|
|
||||||
private val raycaster = Raycaster()
|
private val raycaster = Raycaster()
|
||||||
@ -195,7 +192,7 @@ public class ThreeCanvas(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override fun render(vision: Solid) {
|
public fun render(vision: Solid) {
|
||||||
scene.children.find { it.name == "@root" }?.let {
|
scene.children.find { it.name == "@root" }?.let {
|
||||||
//Throw error is something is already rendered here
|
//Throw error is something is already rendered here
|
||||||
error("Root object already is present in the canvas")
|
error("Root object already is present in the canvas")
|
||||||
|
@ -4,14 +4,13 @@ import hep.dataforge.context.*
|
|||||||
import hep.dataforge.meta.Meta
|
import hep.dataforge.meta.Meta
|
||||||
import hep.dataforge.names.*
|
import hep.dataforge.names.*
|
||||||
import hep.dataforge.vision.Vision
|
import hep.dataforge.vision.Vision
|
||||||
|
import hep.dataforge.vision.VisionForge
|
||||||
import hep.dataforge.vision.client.ElementVisionRenderer
|
import hep.dataforge.vision.client.ElementVisionRenderer
|
||||||
import hep.dataforge.vision.solid.*
|
import hep.dataforge.vision.solid.*
|
||||||
import hep.dataforge.vision.solid.specifications.Canvas3DOptions
|
import hep.dataforge.vision.solid.specifications.Canvas3DOptions
|
||||||
import hep.dataforge.vision.visible
|
import hep.dataforge.vision.visible
|
||||||
import info.laht.threekt.core.Object3D
|
import info.laht.threekt.core.Object3D
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.flow.launchIn
|
|
||||||
import kotlinx.coroutines.flow.onEach
|
|
||||||
import org.w3c.dom.Element
|
import org.w3c.dom.Element
|
||||||
import org.w3c.dom.HTMLElement
|
import org.w3c.dom.HTMLElement
|
||||||
import kotlin.collections.set
|
import kotlin.collections.set
|
||||||
@ -151,6 +150,14 @@ public class ThreePlugin : AbstractPlugin(), ElementVisionRenderer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ensure that [ThreePlugin] is loaded in the global [VisionForge] context
|
||||||
|
*/
|
||||||
|
@JsExport
|
||||||
|
public fun loadThreeJs(){
|
||||||
|
VisionForge.plugins.fetch(ThreePlugin)
|
||||||
|
}
|
||||||
|
|
||||||
public fun ThreePlugin.render(
|
public fun ThreePlugin.render(
|
||||||
element: HTMLElement,
|
element: HTMLElement,
|
||||||
obj: Solid,
|
obj: Solid,
|
||||||
|
@ -1,20 +1,9 @@
|
|||||||
package hep.dataforge.vision.three.server
|
package hep.dataforge.vision.three.server
|
||||||
|
|
||||||
import hep.dataforge.context.Global
|
import hep.dataforge.vision.renderVisionsInWindow
|
||||||
import hep.dataforge.vision.client.VisionClient
|
import hep.dataforge.vision.solid.three.loadThreeJs
|
||||||
import hep.dataforge.vision.client.renderAllVisions
|
|
||||||
import hep.dataforge.vision.solid.three.ThreePlugin
|
|
||||||
import kotlinx.browser.window
|
|
||||||
|
|
||||||
public fun main() {
|
public fun main() {
|
||||||
//Loading three-js renderer
|
loadThreeJs()
|
||||||
val visionContext = Global.context("threejs") {
|
renderVisionsInWindow()
|
||||||
plugin(ThreePlugin)
|
|
||||||
}
|
|
||||||
val clientManager = visionContext.plugins.fetch(VisionClient)
|
|
||||||
|
|
||||||
//Fetch from server and render visions for all outputs
|
|
||||||
window.onload = {
|
|
||||||
clientManager.renderAllVisions()
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -2,10 +2,12 @@ package hep.dataforge.vision.three.server
|
|||||||
|
|
||||||
import hep.dataforge.context.Context
|
import hep.dataforge.context.Context
|
||||||
import hep.dataforge.meta.DFExperimental
|
import hep.dataforge.meta.DFExperimental
|
||||||
import hep.dataforge.vision.ResourceLocation
|
|
||||||
import hep.dataforge.vision.html.HtmlVisionFragment
|
import hep.dataforge.vision.html.HtmlVisionFragment
|
||||||
import hep.dataforge.vision.makeVisionFile
|
import hep.dataforge.vision.html.ResourceLocation
|
||||||
import hep.dataforge.vision.scriptHeader
|
import hep.dataforge.vision.html.scriptHeader
|
||||||
|
import hep.dataforge.vision.makeFile
|
||||||
|
import hep.dataforge.vision.page
|
||||||
|
import java.awt.Desktop
|
||||||
import java.nio.file.Path
|
import java.nio.file.Path
|
||||||
|
|
||||||
|
|
||||||
@ -14,12 +16,15 @@ public fun VisionServer.useThreeJs(): Unit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@DFExperimental
|
@DFExperimental
|
||||||
public fun Context.makeVisionFile(
|
public fun Context.makeThreeJsFile(
|
||||||
fragment: HtmlVisionFragment,
|
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,
|
||||||
): Unit = makeVisionFile(fragment, path = path, title = title, show = show) { actualPath ->
|
): Unit {
|
||||||
scriptHeader("js/visionforge-three.js", actualPath, resourceLocation)
|
val actualPath = page(title, content).makeFile(path) { actualPath ->
|
||||||
|
mapOf("threeJs" to scriptHeader("js/visionforge-three.js", actualPath, resourceLocation))
|
||||||
|
}
|
||||||
|
if (show) Desktop.getDesktop().browse(actualPath.toFile().toURI())
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user