forked from kscience/visionforge
Generalize three with controls
This commit is contained in:
parent
5afa9117c4
commit
1f8700efde
@ -22,7 +22,7 @@ allprojects {
|
||||
}
|
||||
|
||||
group = "space.kscience"
|
||||
version = "0.2.0-dev-16"
|
||||
version = "0.2.0-dev-17"
|
||||
}
|
||||
|
||||
subprojects {
|
||||
|
@ -14,10 +14,15 @@ repositories{
|
||||
kotlin {
|
||||
|
||||
js(IR) {
|
||||
useCommonJs()
|
||||
browser {
|
||||
webpackTask {
|
||||
this.outputFileName = "js/visionforge-playground.js"
|
||||
}
|
||||
commonWebpackConfig {
|
||||
sourceMaps = false
|
||||
cssSupport.enabled = false
|
||||
}
|
||||
}
|
||||
binaries.executable()
|
||||
}
|
||||
@ -54,7 +59,7 @@ kotlin {
|
||||
|
||||
val jsMain by getting{
|
||||
dependencies {
|
||||
api(project(":ui:bootstrap"))
|
||||
implementation(project(":ui:ring"))
|
||||
api(project(":visionforge-threejs"))
|
||||
}
|
||||
}
|
||||
|
@ -1,10 +1,10 @@
|
||||
import space.kscience.dataforge.misc.DFExperimental
|
||||
import space.kscience.visionforge.plotly.PlotlyPlugin
|
||||
import space.kscience.visionforge.ring.ThreeWithControls
|
||||
import space.kscience.visionforge.runVisionClient
|
||||
import space.kscience.visionforge.solid.three.ThreePlugin
|
||||
|
||||
@DFExperimental
|
||||
fun main() = runVisionClient {
|
||||
plugin(PlotlyPlugin)
|
||||
plugin(ThreePlugin)
|
||||
plugin(ThreeWithControls)
|
||||
}
|
@ -3,14 +3,17 @@ package space.kscience.visionforge.examples
|
||||
import space.kscience.dataforge.context.Context
|
||||
import space.kscience.gdml.*
|
||||
import space.kscience.visionforge.gdml.toVision
|
||||
import space.kscience.visionforge.html.ResourceLocation
|
||||
import space.kscience.visionforge.solid.Solids
|
||||
import space.kscience.visionforge.visible
|
||||
import java.nio.file.Path
|
||||
|
||||
fun main() {
|
||||
val context = Context {
|
||||
plugin(Solids)
|
||||
}
|
||||
|
||||
context.makeVisionFile {
|
||||
context.makeVisionFile(Path.of("curves.html"), resourceLocation = ResourceLocation.EMBED) {
|
||||
vision("canvas") {
|
||||
Gdml {
|
||||
// geometry variables
|
||||
@ -39,7 +42,7 @@ fun main() {
|
||||
|
||||
structure {
|
||||
val worldMaterial = materials.composite("G4_AIR")
|
||||
val worldBox = solids.box(worldSize, worldSize, worldSize)
|
||||
val worldBox = solids.box(worldSize, worldSize, worldSize, name = "world")
|
||||
|
||||
val shieldingMaterial = materials.composite("G4_Pb")
|
||||
val scintillatorMaterial = materials.composite("BC408")
|
||||
@ -221,7 +224,14 @@ fun main() {
|
||||
}
|
||||
}
|
||||
}.toVision {
|
||||
this.solidAction
|
||||
configure { parent, solid, material ->
|
||||
//disable visibility for the world box
|
||||
if(solid.name == "world"){
|
||||
visible = false
|
||||
}
|
||||
//make all solids semi-transparent
|
||||
transparent()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
3
demo/playground/webpack.config.d/01.ring.js
vendored
Normal file
3
demo/playground/webpack.config.d/01.ring.js
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
const ringConfig = require('@jetbrains/ring-ui/webpack.config').config;
|
||||
|
||||
config.module.rules.push(...ringConfig.module.rules)
|
@ -8,10 +8,15 @@ description = "Jupyter api artifact for GDML rendering"
|
||||
kotlin{
|
||||
explicitApi = null
|
||||
js{
|
||||
useCommonJs()
|
||||
browser {
|
||||
webpackTask {
|
||||
this.outputFileName = "js/gdml-jupyter.js"
|
||||
}
|
||||
commonWebpackConfig {
|
||||
sourceMaps = false
|
||||
cssSupport.enabled = false
|
||||
}
|
||||
}
|
||||
binaries.executable()
|
||||
}
|
||||
@ -42,7 +47,7 @@ kotlin{
|
||||
jsMain {
|
||||
dependencies {
|
||||
api(project(":visionforge-threejs"))
|
||||
implementation(project(":ui:bootstrap"))
|
||||
implementation(project(":ui:ring"))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,27 +1,12 @@
|
||||
package space.kscience.visionforge.gdml.jupyter
|
||||
|
||||
import kotlinx.css.ListStyleType
|
||||
import kotlinx.css.listStyleType
|
||||
import space.kscience.dataforge.misc.DFExperimental
|
||||
import space.kscience.visionforge.bootstrap.useBootstrap
|
||||
import space.kscience.visionforge.ring.ThreeWithControls
|
||||
import space.kscience.visionforge.runVisionClient
|
||||
import styled.injectGlobal
|
||||
|
||||
@DFExperimental
|
||||
@JsExport
|
||||
fun main(): Unit = runVisionClient {
|
||||
useBootstrap()
|
||||
injectGlobal {
|
||||
rule("ul.nav") {
|
||||
listStyleType = ListStyleType.none
|
||||
}
|
||||
|
||||
rule(".treeStyles-tree") {
|
||||
listStyleType = ListStyleType.none
|
||||
}
|
||||
|
||||
rule("ol.breadcrumb") {
|
||||
listStyleType = ListStyleType.none
|
||||
}
|
||||
}
|
||||
plugin(ThreeWithControls)
|
||||
}
|
||||
|
||||
|
@ -1,83 +0,0 @@
|
||||
package space.kscience.visionforge.gdml.jupyter
|
||||
|
||||
import kotlinx.css.*
|
||||
import react.RProps
|
||||
import react.child
|
||||
import react.dom.h1
|
||||
import react.functionalComponent
|
||||
import react.useState
|
||||
import space.kscience.dataforge.context.Context
|
||||
import space.kscience.dataforge.names.Name
|
||||
import space.kscience.visionforge.Vision
|
||||
import space.kscience.visionforge.bootstrap.gridRow
|
||||
import space.kscience.visionforge.bootstrap.nameCrumbs
|
||||
import space.kscience.visionforge.bootstrap.threeControls
|
||||
import space.kscience.visionforge.react.ThreeCanvasComponent
|
||||
import space.kscience.visionforge.react.flexColumn
|
||||
import space.kscience.visionforge.solid.Solid
|
||||
import space.kscience.visionforge.solid.specifications.Canvas3DOptions
|
||||
import space.kscience.visionforge.solid.three.ThreeCanvas
|
||||
import styled.css
|
||||
import styled.styledDiv
|
||||
|
||||
external interface GdmlViewProps : RProps {
|
||||
var context: Context
|
||||
var rootVision: Vision?
|
||||
var selected: Name?
|
||||
}
|
||||
|
||||
@JsExport
|
||||
val GdmlView = functionalComponent<GdmlViewProps>("GdmlView") { props ->
|
||||
var selected by useState { props.selected }
|
||||
var canvas: ThreeCanvas? by useState { null }
|
||||
var vision: Vision? by useState { props.rootVision }
|
||||
|
||||
val onSelect: (Name?) -> Unit = {
|
||||
selected = it
|
||||
}
|
||||
|
||||
gridRow {
|
||||
flexColumn {
|
||||
css {
|
||||
+"col-lg-9"
|
||||
height = 100.vh
|
||||
}
|
||||
styledDiv {
|
||||
css {
|
||||
+"mx-auto"
|
||||
+"page-header"
|
||||
}
|
||||
h1 { +"GDML/JSON loader demo" }
|
||||
}
|
||||
nameCrumbs(selected, "World", onSelect)
|
||||
//canvas
|
||||
|
||||
child(ThreeCanvasComponent) {
|
||||
attrs {
|
||||
this.context = props.context
|
||||
this.obj = vision as? Solid
|
||||
this.selected = selected
|
||||
this.options = Canvas3DOptions.invoke {
|
||||
this.onSelect = onSelect
|
||||
}
|
||||
this.canvasCallback = {
|
||||
canvas = it
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
flexColumn {
|
||||
css {
|
||||
+"col-lg-3"
|
||||
padding(top = 4.px)
|
||||
//border(1.px, BorderStyle.solid, Color.lightGray)
|
||||
height = 100.vh
|
||||
overflowY = Overflow.auto
|
||||
}
|
||||
canvas?.let {
|
||||
threeControls(it, selected, onSelect)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -36,9 +36,6 @@ internal class GdmlForJupyter : JupyterIntegration() {
|
||||
js("three") {
|
||||
classPath("js/gdml-jupyter.js")
|
||||
}
|
||||
// css("override") {
|
||||
// classPath("css/jupyter-override.css")
|
||||
// }
|
||||
}
|
||||
|
||||
import(
|
||||
|
3
jupyter/visionforge-gdml-jupyter/webpack.config.d/01.ring.js
vendored
Normal file
3
jupyter/visionforge-gdml-jupyter/webpack.config.d/01.ring.js
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
const ringConfig = require('@jetbrains/ring-ui/webpack.config').config;
|
||||
|
||||
config.module.rules.push(...ringConfig.module.rules)
|
@ -2,6 +2,8 @@ package space.kscience.visionforge.react
|
||||
|
||||
import kotlinx.css.Display
|
||||
import kotlinx.css.display
|
||||
import kotlinx.css.height
|
||||
import kotlinx.css.pct
|
||||
import org.w3c.dom.Element
|
||||
import org.w3c.dom.HTMLElement
|
||||
import react.*
|
||||
@ -60,6 +62,7 @@ public val ThreeCanvasComponent: FunctionalComponent<ThreeCanvasProps> = functio
|
||||
styledDiv {
|
||||
css {
|
||||
display = Display.contents
|
||||
height = 100.pct
|
||||
}
|
||||
ref = elementRef
|
||||
}
|
||||
|
@ -21,6 +21,7 @@ dependencies{
|
||||
implementation(npm("@jetbrains/icons", "3.14.1"))
|
||||
implementation(npm("@jetbrains/ring-ui", "4.0.7"))
|
||||
implementation(npm("core-js","3.12.1"))
|
||||
implementation(npm("file-saver", "2.0.2"))
|
||||
compileOnly(npm("url-loader","4.1.1"))
|
||||
compileOnly(npm("postcss-loader","5.2.0"))
|
||||
compileOnly(npm("source-map-loader","2.0.1"))
|
||||
|
23
ui/ring/src/main/kotlin/ringui/grid/Col.kt
Normal file
23
ui/ring/src/main/kotlin/ringui/grid/Col.kt
Normal file
@ -0,0 +1,23 @@
|
||||
package ringui.grid
|
||||
|
||||
import react.RBuilder
|
||||
import react.RHandler
|
||||
import react.dom.WithClassName
|
||||
|
||||
public external interface ColProps : WithClassName {
|
||||
public var xs: dynamic // number or boolean
|
||||
public var sm: dynamic // number or boolean
|
||||
public var md: dynamic // number or boolean
|
||||
public var lg: dynamic // number or boolean
|
||||
public var xsOffset: Number
|
||||
public var smOffset: Number
|
||||
public var mdOffset: Number
|
||||
public var lgOffset: Number
|
||||
public var reverse: Boolean
|
||||
}
|
||||
|
||||
public fun RBuilder.ringCol(handler: RHandler<ColProps>){
|
||||
GridModule.Col {
|
||||
handler()
|
||||
}
|
||||
}
|
20
ui/ring/src/main/kotlin/ringui/grid/Grid.kt
Normal file
20
ui/ring/src/main/kotlin/ringui/grid/Grid.kt
Normal file
@ -0,0 +1,20 @@
|
||||
package ringui.grid
|
||||
|
||||
import react.RBuilder
|
||||
import react.RClass
|
||||
import react.RHandler
|
||||
import react.RProps
|
||||
|
||||
@JsModule("@jetbrains/ring-ui/components/grid/grid")
|
||||
internal external object GridModule {
|
||||
val Grid: RClass<RProps>
|
||||
val Row: RClass<RowProps>
|
||||
val Col: RClass<dynamic>
|
||||
}
|
||||
|
||||
|
||||
public fun RBuilder.ringGrid(handler: RHandler<RProps>) {
|
||||
GridModule.Grid {
|
||||
handler()
|
||||
}
|
||||
}
|
33
ui/ring/src/main/kotlin/ringui/grid/Row.kt
Normal file
33
ui/ring/src/main/kotlin/ringui/grid/Row.kt
Normal file
@ -0,0 +1,33 @@
|
||||
package ringui.grid
|
||||
|
||||
import react.RBuilder
|
||||
import react.RHandler
|
||||
import react.dom.WithClassName
|
||||
|
||||
public enum class RowPosition {
|
||||
xs,
|
||||
sm,
|
||||
md,
|
||||
lg
|
||||
}
|
||||
|
||||
public external interface RowProps : WithClassName {
|
||||
public var reverse: Boolean
|
||||
public var start: RowPosition
|
||||
public var center: RowPosition
|
||||
public var end: RowPosition
|
||||
public var top: RowPosition
|
||||
public var middle: RowPosition
|
||||
public var baseline: RowPosition
|
||||
public var bottom: RowPosition
|
||||
public var around: RowPosition
|
||||
public var between: RowPosition
|
||||
public var first: RowPosition
|
||||
public var last: RowPosition
|
||||
}
|
||||
|
||||
public fun RBuilder.ringRow(handler: RHandler<RowProps>){
|
||||
GridModule.Row {
|
||||
handler()
|
||||
}
|
||||
}
|
@ -0,0 +1,87 @@
|
||||
package space.kscience.visionforge.ring
|
||||
|
||||
import kotlinx.css.*
|
||||
import react.RProps
|
||||
import react.child
|
||||
import react.functionalComponent
|
||||
import react.useState
|
||||
import ringui.grid.ringCol
|
||||
import ringui.grid.ringGrid
|
||||
import ringui.grid.ringRow
|
||||
import space.kscience.dataforge.context.Context
|
||||
import space.kscience.dataforge.names.Name
|
||||
import space.kscience.visionforge.Vision
|
||||
import space.kscience.visionforge.react.ThreeCanvasComponent
|
||||
import space.kscience.visionforge.solid.Solid
|
||||
import space.kscience.visionforge.solid.specifications.Canvas3DOptions
|
||||
import space.kscience.visionforge.solid.three.ThreeCanvas
|
||||
import styled.css
|
||||
import styled.styledDiv
|
||||
|
||||
public external interface GdmlViewProps : RProps {
|
||||
public var context: Context
|
||||
public var rootVision: Vision?
|
||||
public var selected: Name?
|
||||
}
|
||||
|
||||
@JsExport
|
||||
public val ThreeViewWithControls: (props: GdmlViewProps) -> dynamic =
|
||||
functionalComponent<GdmlViewProps>("ThreeViewWithControls") { props ->
|
||||
var selected by useState { props.selected }
|
||||
var canvas: ThreeCanvas? by useState { null }
|
||||
|
||||
val onSelect: (Name?) -> Unit = {
|
||||
selected = it
|
||||
}
|
||||
|
||||
styledDiv {
|
||||
css {
|
||||
height = 100.pct
|
||||
}
|
||||
ringGrid {
|
||||
ringRow {
|
||||
ringCol {
|
||||
attrs {
|
||||
xs = 12
|
||||
sm = 12
|
||||
md = 8
|
||||
lg = 9
|
||||
}
|
||||
child(ThreeCanvasComponent) {
|
||||
attrs {
|
||||
this.context = props.context
|
||||
this.obj = props.rootVision as? Solid
|
||||
this.selected = selected
|
||||
this.options = Canvas3DOptions.invoke {
|
||||
this.onSelect = onSelect
|
||||
}
|
||||
this.canvasCallback = {
|
||||
canvas = it
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
ringCol {
|
||||
attrs {
|
||||
xs = 12
|
||||
sm = 12
|
||||
md = 4
|
||||
lg = 3
|
||||
}
|
||||
styledDiv {
|
||||
css {
|
||||
padding(top = 4.px)
|
||||
//border(1.px, BorderStyle.solid, Color.lightGray)
|
||||
height = 100.pct
|
||||
overflowY = Overflow.auto
|
||||
}
|
||||
canvas?.let {
|
||||
ringThreeControls(it, selected, onSelect)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package space.kscience.visionforge.gdml.jupyter
|
||||
package space.kscience.visionforge.ring
|
||||
|
||||
import org.w3c.dom.Element
|
||||
import react.child
|
||||
@ -15,8 +15,8 @@ import space.kscience.visionforge.solid.Solid
|
||||
import space.kscience.visionforge.solid.three.ThreePlugin
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
class ThreeWithControls : AbstractPlugin(), ElementVisionRenderer {
|
||||
val three by require(ThreePlugin)
|
||||
public class ThreeWithControls : AbstractPlugin(), ElementVisionRenderer {
|
||||
public val three by require(ThreePlugin)
|
||||
|
||||
override val tag: PluginTag get() = Companion.tag
|
||||
|
||||
@ -25,7 +25,7 @@ class ThreeWithControls : AbstractPlugin(), ElementVisionRenderer {
|
||||
|
||||
override fun render(element: Element, vision: Vision, meta: Meta) {
|
||||
react.dom.render(element) {
|
||||
child(GdmlView) {
|
||||
child(ThreeViewWithControls) {
|
||||
attrs {
|
||||
this.context = this@ThreeWithControls.context
|
||||
this.rootVision = vision
|
||||
@ -41,7 +41,7 @@ class ThreeWithControls : AbstractPlugin(), ElementVisionRenderer {
|
||||
}
|
||||
}
|
||||
|
||||
companion object : PluginFactory<ThreeWithControls> {
|
||||
public companion object : PluginFactory<ThreeWithControls> {
|
||||
override val tag: PluginTag = PluginTag("vision.threejs.withControls", PluginTag.DATAFORGE_GROUP)
|
||||
override val type: KClass<ThreeWithControls> = ThreeWithControls::class
|
||||
override fun invoke(meta: Meta, context: Context): ThreeWithControls = ThreeWithControls()
|
@ -217,10 +217,7 @@ public fun VisionClient.renderAllVisions(): Unit = whenDocumentLoaded {
|
||||
*/
|
||||
public fun runVisionClient(contextBuilder: ContextBuilder.() -> Unit) {
|
||||
console.info("Starting VisionForge context")
|
||||
val context = Context("VisionForge"){
|
||||
contextBuilder()
|
||||
//plugin(VisionClient)
|
||||
}
|
||||
val context = Context("VisionForge", contextBuilder)
|
||||
val visionClient = context.fetch(VisionClient)
|
||||
window.asDynamic()[RENDER_FUNCTION_NAME] = visionClient::renderAllVisionsById
|
||||
|
||||
|
@ -3,6 +3,7 @@ package space.kscience.visionforge.html
|
||||
import kotlinx.html.link
|
||||
import kotlinx.html.script
|
||||
import kotlinx.html.unsafe
|
||||
import org.slf4j.LoggerFactory
|
||||
import space.kscience.dataforge.misc.DFExperimental
|
||||
import space.kscience.visionforge.VisionManager
|
||||
import java.nio.file.Files
|
||||
@ -49,18 +50,22 @@ private fun ByteArray.toHexString() = asUByteArray().joinToString("") { it.toStr
|
||||
*/
|
||||
@OptIn(ExperimentalPathApi::class)
|
||||
internal fun checkOrStoreFile(htmlPath: Path, filePath: Path, resource: String): Path {
|
||||
//TODO add logging
|
||||
val fullPath = htmlPath.resolveSibling(filePath).toAbsolutePath().resolve(resource)
|
||||
val logger = LoggerFactory.getLogger("")
|
||||
|
||||
val bytes = VisionManager::class.java.getResourceAsStream("/$resource").readAllBytes()
|
||||
logger.info("Resolving or storing resource file $resource")
|
||||
val fullPath = htmlPath.resolveSibling(filePath).toAbsolutePath().resolve(resource)
|
||||
logger.debug("Full path to resource file $resource: $fullPath")
|
||||
|
||||
val bytes = VisionManager.Companion::class.java.getResourceAsStream("/$resource")?.readAllBytes()
|
||||
?: error("Resource $resource not found on classpath")
|
||||
val md = MessageDigest.getInstance("MD5")
|
||||
|
||||
val checksum = md.digest(bytes).toHexString()
|
||||
|
||||
val md5File = fullPath.resolveSibling(fullPath.fileName.toString() + ".md5")
|
||||
val skip: Boolean = Files.exists(fullPath) && Files.exists(md5File) && md5File.readText() == checksum
|
||||
|
||||
if (!skip) {
|
||||
logger.debug("File $fullPath does not exist or wrong checksum. Writing file")
|
||||
Files.createDirectories(fullPath.parent)
|
||||
Files.write(fullPath, bytes, StandardOpenOption.CREATE, StandardOpenOption.WRITE)
|
||||
Files.write(md5File, checksum.encodeToByteArray(), StandardOpenOption.CREATE, StandardOpenOption.WRITE)
|
||||
|
@ -48,8 +48,8 @@ public class GdmlTransformer {
|
||||
useStyle(name)
|
||||
}
|
||||
|
||||
public fun Solid.opaque() {
|
||||
useStyle("opaque") {
|
||||
public fun Solid.transparent() {
|
||||
useStyle("transparent") {
|
||||
SolidMaterial.MATERIAL_OPACITY_KEY put 0.3
|
||||
"edges.enabled" put true
|
||||
}
|
||||
@ -73,7 +73,7 @@ public class GdmlTransformer {
|
||||
{ parent, solid, material ->
|
||||
val styleName = "materials.${material.name}"
|
||||
|
||||
if (parent.physVolumes.isNotEmpty()) opaque()
|
||||
if (parent.physVolumes.isNotEmpty()) transparent()
|
||||
|
||||
useStyle(styleName) {
|
||||
val vfMaterial = SolidMaterial().apply {
|
||||
@ -85,6 +85,13 @@ public class GdmlTransformer {
|
||||
}
|
||||
private set
|
||||
|
||||
public fun configure(block: Solid.(parent: GdmlVolume, solid: GdmlSolid, material: GdmlMaterial) -> Unit) {
|
||||
val oldConfigure = configureSolid
|
||||
configureSolid = { parent: GdmlVolume, solid: GdmlSolid, material: GdmlMaterial ->
|
||||
oldConfigure(parent, solid, material)
|
||||
block(parent, solid, material)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public companion object {
|
||||
|
@ -3,6 +3,7 @@ plugins {
|
||||
}
|
||||
|
||||
kotlin{
|
||||
explicitApi = null
|
||||
js{
|
||||
binaries.library()
|
||||
}
|
||||
|
@ -110,7 +110,6 @@ public class ThreeCanvas(
|
||||
width = "100%"
|
||||
height = "100%"
|
||||
display = "block"
|
||||
zIndex = "1000"
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user