forked from kscience/visionforge
Update examples
This commit is contained in:
parent
95459422d6
commit
8a8bac48db
@ -1,6 +1,9 @@
|
||||
package space.kscience.visionforge.gdml.demo
|
||||
|
||||
import kotlinx.browser.window
|
||||
import kotlinx.coroutines.CompletableDeferred
|
||||
import kotlinx.coroutines.Deferred
|
||||
import org.w3c.files.File
|
||||
import org.w3c.files.FileReader
|
||||
import org.w3c.files.get
|
||||
import react.*
|
||||
@ -27,9 +30,16 @@ external interface GDMLAppProps : RProps {
|
||||
@JsExport
|
||||
val GDMLApp = functionalComponent<GDMLAppProps>("GDMLApp") { props ->
|
||||
val visionManager = useMemo(props.context) { props.context.fetch(Solids).visionManager }
|
||||
var vision: Solid? by useState { props.vision?.apply { root(visionManager) } }
|
||||
var deferredVision: Deferred<Solid?> by useState {
|
||||
CompletableDeferred(props.vision)
|
||||
}
|
||||
|
||||
fun loadData(name: String, data: String) {
|
||||
fun readFileAsync(file: File): Deferred<Solid?> {
|
||||
val deferred = CompletableDeferred<Solid?>()
|
||||
FileReader().apply {
|
||||
onload = {
|
||||
val data = result as String
|
||||
val name = file.name
|
||||
val parsedVision = when {
|
||||
name.endsWith(".gdml") || name.endsWith(".xml") -> {
|
||||
val gdml = Gdml.decodeFromString(data)
|
||||
@ -45,14 +55,18 @@ val GDMLApp = functionalComponent<GDMLAppProps>("GDMLApp") { props ->
|
||||
error("File extension is not recognized: $name")
|
||||
}
|
||||
}
|
||||
deferred.complete(parsedVision as? Solid ?: error("Parsed vision is not a solid"))
|
||||
}
|
||||
readAsText(file)
|
||||
}
|
||||
|
||||
vision = parsedVision as? Solid ?: error("Parsed vision is not a solid")
|
||||
return deferred
|
||||
}
|
||||
|
||||
child(ThreeCanvasWithControls) {
|
||||
attrs {
|
||||
this.context = props.context
|
||||
this.solid = vision
|
||||
this.builderOfSolid = deferredVision
|
||||
this.selected = props.selected
|
||||
tab("Load") {
|
||||
h2 {
|
||||
@ -61,13 +75,7 @@ val GDMLApp = functionalComponent<GDMLAppProps>("GDMLApp") { props ->
|
||||
fileDrop("(drag file here)") { files ->
|
||||
val file = files?.get(0)
|
||||
if (file != null) {
|
||||
FileReader().apply {
|
||||
onload = {
|
||||
val string = result as String
|
||||
loadData(file.name, string)
|
||||
}
|
||||
readAsText(file)
|
||||
}
|
||||
deferredVision = readFileAsync(file)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,4 @@
|
||||
import kotlinx.browser.document
|
||||
import kotlinx.coroutines.GlobalScope
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.isActive
|
||||
import kotlinx.coroutines.launch
|
||||
@ -17,6 +16,7 @@ import space.kscience.visionforge.VisionClient
|
||||
import space.kscience.visionforge.plotly.PlotlyPlugin
|
||||
import space.kscience.visionforge.ring.ThreeCanvasWithControls
|
||||
import space.kscience.visionforge.ring.ThreeWithControlsPlugin
|
||||
import space.kscience.visionforge.ring.solid
|
||||
import space.kscience.visionforge.solid.*
|
||||
import space.kscience.visionforge.startApplication
|
||||
import styled.css
|
||||
@ -38,13 +38,30 @@ private class JsPlaygroundApp : Application {
|
||||
|
||||
val bouncingSphereTrace = Trace()
|
||||
|
||||
val bouncingSphere = SolidGroup {
|
||||
render(element) {
|
||||
styledDiv {
|
||||
css {
|
||||
padding(0.pt)
|
||||
margin(0.pt)
|
||||
height = 100.vh
|
||||
width = 100.vw
|
||||
}
|
||||
SmartTabs("gravity") {
|
||||
Tab("gravity") {
|
||||
styledDiv {
|
||||
css {
|
||||
height = 50.vh
|
||||
}
|
||||
child(ThreeCanvasWithControls) {
|
||||
attrs {
|
||||
context = playgroundContext
|
||||
solid {
|
||||
sphere(5.0, "ball") {
|
||||
detail = 16
|
||||
color("red")
|
||||
val h = 100.0
|
||||
y = h
|
||||
GlobalScope.launch {
|
||||
launch {
|
||||
val g = 10.0
|
||||
val dt = 0.1
|
||||
var time = 0.0
|
||||
@ -67,40 +84,6 @@ private class JsPlaygroundApp : Application {
|
||||
y = -2.5
|
||||
}
|
||||
}
|
||||
val random = Random(112233)
|
||||
|
||||
val visionOfSpheres = SolidGroup {
|
||||
repeat(100) {
|
||||
sphere(5, name = "sphere[$it]") {
|
||||
x = random.nextDouble(-300.0, 300.0)
|
||||
y = random.nextDouble(-300.0, 300.0)
|
||||
z = random.nextDouble(-300.0, 300.0)
|
||||
material {
|
||||
color(random.nextInt())
|
||||
}
|
||||
detail = 16
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
render(element) {
|
||||
styledDiv {
|
||||
css {
|
||||
padding(0.pt)
|
||||
margin(0.pt)
|
||||
height = 100.vh
|
||||
width = 100.vw
|
||||
}
|
||||
SmartTabs("gravity") {
|
||||
Tab("gravity") {
|
||||
styledDiv {
|
||||
css{
|
||||
height = 50.vh
|
||||
}
|
||||
child(ThreeCanvasWithControls) {
|
||||
attrs {
|
||||
context = playgroundContext
|
||||
solid = bouncingSphere
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -129,10 +112,28 @@ private class JsPlaygroundApp : Application {
|
||||
// }
|
||||
// }
|
||||
Tab("spheres") {
|
||||
styledDiv {
|
||||
css {
|
||||
height = 90.vh
|
||||
}
|
||||
child(ThreeCanvasWithControls) {
|
||||
val random = Random(112233)
|
||||
attrs {
|
||||
context = playgroundContext
|
||||
solid = visionOfSpheres
|
||||
solid {
|
||||
repeat(100) {
|
||||
sphere(5, name = "sphere[$it]") {
|
||||
x = random.nextDouble(-300.0, 300.0)
|
||||
y = random.nextDouble(-300.0, 300.0)
|
||||
z = random.nextDouble(-300.0, 300.0)
|
||||
material {
|
||||
color(random.nextInt())
|
||||
}
|
||||
detail = 16
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
19
ui/ring/src/main/kotlin/ringui/Loader.kt
Normal file
19
ui/ring/src/main/kotlin/ringui/Loader.kt
Normal file
@ -0,0 +1,19 @@
|
||||
@file:JsModule("@jetbrains/ring-ui/components/loader/loader")
|
||||
@file:JsNonModule
|
||||
|
||||
package ringui
|
||||
|
||||
import react.ComponentClass
|
||||
import react.dom.WithClassName
|
||||
|
||||
// https://github.com/JetBrains/ring-ui/blob/master/components/loader/loader.js
|
||||
public external interface LoaderProps : WithClassName {
|
||||
public var size: Number
|
||||
public var colors: Array<String>
|
||||
public var message: String
|
||||
public var stop: Boolean
|
||||
public var deterministic: Boolean
|
||||
}
|
||||
|
||||
@JsName("default")
|
||||
public external val Loader: ComponentClass<LoaderProps>
|
16
ui/ring/src/main/kotlin/ringui/LoaderScreen.kt
Normal file
16
ui/ring/src/main/kotlin/ringui/LoaderScreen.kt
Normal file
@ -0,0 +1,16 @@
|
||||
@file:JsModule("@jetbrains/ring-ui/components/loader-screen/loader-screen")
|
||||
@file:JsNonModule
|
||||
|
||||
package ringui
|
||||
|
||||
import react.ComponentClass
|
||||
import react.dom.WithClassName
|
||||
|
||||
// https://github.com/JetBrains/ring-ui/blob/master/components/loader-screen/loader-screen.js
|
||||
public external interface LoaderScreenProps : WithClassName {
|
||||
public var containerClassName: String
|
||||
public var message: String
|
||||
}
|
||||
|
||||
@JsName("default")
|
||||
public external val LoaderScreen: ComponentClass<LoaderScreenProps>
|
@ -1,18 +1,19 @@
|
||||
package space.kscience.visionforge.ring
|
||||
|
||||
import kotlinx.coroutines.Deferred
|
||||
import kotlinx.coroutines.async
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.css.*
|
||||
import react.*
|
||||
import react.dom.div
|
||||
import react.dom.span
|
||||
import ringui.Island
|
||||
import ringui.IslandContent
|
||||
import ringui.IslandHeader
|
||||
import ringui.Link
|
||||
import ringui.*
|
||||
import space.kscience.dataforge.context.Context
|
||||
import space.kscience.dataforge.names.Name
|
||||
import space.kscience.dataforge.names.NameToken
|
||||
import space.kscience.dataforge.names.isEmpty
|
||||
import space.kscience.dataforge.names.length
|
||||
import space.kscience.visionforge.Vision
|
||||
import space.kscience.visionforge.VisionGroup
|
||||
import space.kscience.visionforge.computeProperties
|
||||
import space.kscience.visionforge.react.ThreeCanvasComponent
|
||||
@ -20,17 +21,24 @@ import space.kscience.visionforge.react.flexColumn
|
||||
import space.kscience.visionforge.react.flexRow
|
||||
import space.kscience.visionforge.react.propertyEditor
|
||||
import space.kscience.visionforge.solid.Solid
|
||||
import space.kscience.visionforge.solid.SolidGroup
|
||||
import space.kscience.visionforge.solid.specifications.Canvas3DOptions
|
||||
import styled.css
|
||||
import styled.styledDiv
|
||||
|
||||
public external interface ThreeCanvasWithControlsProps : RProps {
|
||||
public var context: Context
|
||||
public var solid: Solid?
|
||||
public var builderOfSolid: Deferred<Solid?>
|
||||
public var selected: Name?
|
||||
public var additionalTabs: Map<String, RBuilder.() -> Unit>?
|
||||
}
|
||||
|
||||
public fun ThreeCanvasWithControlsProps.solid(block: SolidGroup.() -> Unit) {
|
||||
builderOfSolid = context.async {
|
||||
SolidGroup(block)
|
||||
}
|
||||
}
|
||||
|
||||
public fun ThreeCanvasWithControlsProps.tab(title: String, block: RBuilder.() -> Unit) {
|
||||
additionalTabs = (additionalTabs ?: emptyMap()) + (title to block)
|
||||
}
|
||||
@ -72,6 +80,13 @@ public fun RBuilder.nameCrumbs(name: Name?, link: (Name) -> Unit): ReactElement
|
||||
public val ThreeCanvasWithControls: FunctionComponent<ThreeCanvasWithControlsProps> =
|
||||
functionalComponent("ThreeViewWithControls") { props ->
|
||||
var selected by useState { props.selected }
|
||||
var solid: Solid? by useState(null)
|
||||
|
||||
useEffect {
|
||||
props.context.launch {
|
||||
solid = props.builderOfSolid.await()
|
||||
}
|
||||
}
|
||||
|
||||
val onSelect: (Name?) -> Unit = {
|
||||
selected = it
|
||||
@ -83,15 +98,16 @@ public val ThreeCanvasWithControls: FunctionComponent<ThreeCanvasWithControlsPro
|
||||
}
|
||||
}
|
||||
|
||||
val selectedVision = useMemo(selected) {
|
||||
val selectedVision: Vision? = useMemo(props.builderOfSolid, selected) {
|
||||
selected?.let {
|
||||
when {
|
||||
it.isEmpty() -> props.solid
|
||||
else -> (props.solid as? VisionGroup)?.get(it)
|
||||
it.isEmpty() -> solid
|
||||
else -> (solid as? VisionGroup)?.get(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
flexRow {
|
||||
css {
|
||||
height = 100.pct
|
||||
@ -108,14 +124,22 @@ public val ThreeCanvasWithControls: FunctionComponent<ThreeCanvasWithControlsPro
|
||||
position = Position.relative
|
||||
}
|
||||
|
||||
if (solid == null) {
|
||||
LoaderScreen {
|
||||
attrs {
|
||||
message = "Loading Three vision"
|
||||
}
|
||||
}
|
||||
} else {
|
||||
child(ThreeCanvasComponent) {
|
||||
attrs {
|
||||
this.context = props.context
|
||||
this.solid = props.solid
|
||||
this.solid = solid
|
||||
this.selected = selected
|
||||
this.options = options
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
selectedVision?.let { vision ->
|
||||
styledDiv {
|
||||
@ -150,7 +174,8 @@ public val ThreeCanvasWithControls: FunctionComponent<ThreeCanvasWithControlsPro
|
||||
minWidth = 400.px
|
||||
flex(1.0, 10.0, FlexBasis("300px"))
|
||||
}
|
||||
ringThreeControls(options, props.solid, selected, onSelect, additionalTabs = props.additionalTabs)
|
||||
ringThreeControls(options, solid, selected, onSelect, additionalTabs = props.additionalTabs)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
package space.kscience.visionforge.ring
|
||||
|
||||
import kotlinx.coroutines.async
|
||||
import org.w3c.dom.Element
|
||||
import react.child
|
||||
import space.kscience.dataforge.context.AbstractPlugin
|
||||
@ -28,7 +29,7 @@ public class ThreeWithControlsPlugin : AbstractPlugin(), ElementVisionRenderer {
|
||||
child(ThreeCanvasWithControls) {
|
||||
attrs {
|
||||
this.context = this@ThreeWithControlsPlugin.context
|
||||
this.solid = vision as? Solid
|
||||
this.builderOfSolid = context.async { vision as Solid}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,10 @@
|
||||
package space.kscience.visionforge
|
||||
|
||||
import kotlinx.browser.document
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.dom.hasClass
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
import kotlin.coroutines.EmptyCoroutineContext
|
||||
|
||||
|
||||
public external val module: Module
|
||||
@ -25,7 +28,10 @@ public external interface Module {
|
||||
*
|
||||
* Base interface for applications supporting Hot Module Replacement (HMR).
|
||||
*/
|
||||
public interface Application {
|
||||
public interface Application: CoroutineScope {
|
||||
|
||||
override val coroutineContext: CoroutineContext get() = EmptyCoroutineContext
|
||||
|
||||
/**
|
||||
* Starting point for an application.
|
||||
* @param state Initial state between Hot Module Replacement (HMR).
|
||||
|
Loading…
Reference in New Issue
Block a user