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
|
package space.kscience.visionforge.gdml.demo
|
||||||
|
|
||||||
import kotlinx.browser.window
|
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.FileReader
|
||||||
import org.w3c.files.get
|
import org.w3c.files.get
|
||||||
import react.*
|
import react.*
|
||||||
@ -27,32 +30,43 @@ external interface GDMLAppProps : RProps {
|
|||||||
@JsExport
|
@JsExport
|
||||||
val GDMLApp = functionalComponent<GDMLAppProps>("GDMLApp") { props ->
|
val GDMLApp = functionalComponent<GDMLAppProps>("GDMLApp") { props ->
|
||||||
val visionManager = useMemo(props.context) { props.context.fetch(Solids).visionManager }
|
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 parsedVision = when {
|
val deferred = CompletableDeferred<Solid?>()
|
||||||
name.endsWith(".gdml") || name.endsWith(".xml") -> {
|
FileReader().apply {
|
||||||
val gdml = Gdml.decodeFromString(data)
|
onload = {
|
||||||
gdml.toVision().apply {
|
val data = result as String
|
||||||
root(visionManager)
|
val name = file.name
|
||||||
console.info("Marking layers for file $name")
|
val parsedVision = when {
|
||||||
markLayers()
|
name.endsWith(".gdml") || name.endsWith(".xml") -> {
|
||||||
|
val gdml = Gdml.decodeFromString(data)
|
||||||
|
gdml.toVision().apply {
|
||||||
|
root(visionManager)
|
||||||
|
console.info("Marking layers for file $name")
|
||||||
|
markLayers()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
name.endsWith(".json") -> visionManager.decodeFromString(data)
|
||||||
|
else -> {
|
||||||
|
window.alert("File extension is not recognized: $name")
|
||||||
|
error("File extension is not recognized: $name")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
deferred.complete(parsedVision as? Solid ?: error("Parsed vision is not a solid"))
|
||||||
}
|
}
|
||||||
name.endsWith(".json") -> visionManager.decodeFromString(data)
|
readAsText(file)
|
||||||
else -> {
|
|
||||||
window.alert("File extension is not recognized: $name")
|
|
||||||
error("File extension is not recognized: $name")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
vision = parsedVision as? Solid ?: error("Parsed vision is not a solid")
|
return deferred
|
||||||
}
|
}
|
||||||
|
|
||||||
child(ThreeCanvasWithControls) {
|
child(ThreeCanvasWithControls) {
|
||||||
attrs {
|
attrs {
|
||||||
this.context = props.context
|
this.context = props.context
|
||||||
this.solid = vision
|
this.builderOfSolid = deferredVision
|
||||||
this.selected = props.selected
|
this.selected = props.selected
|
||||||
tab("Load") {
|
tab("Load") {
|
||||||
h2 {
|
h2 {
|
||||||
@ -61,13 +75,7 @@ val GDMLApp = functionalComponent<GDMLAppProps>("GDMLApp") { props ->
|
|||||||
fileDrop("(drag file here)") { files ->
|
fileDrop("(drag file here)") { files ->
|
||||||
val file = files?.get(0)
|
val file = files?.get(0)
|
||||||
if (file != null) {
|
if (file != null) {
|
||||||
FileReader().apply {
|
deferredVision = readFileAsync(file)
|
||||||
onload = {
|
|
||||||
val string = result as String
|
|
||||||
loadData(file.name, string)
|
|
||||||
}
|
|
||||||
readAsText(file)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import kotlinx.browser.document
|
import kotlinx.browser.document
|
||||||
import kotlinx.coroutines.GlobalScope
|
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
import kotlinx.coroutines.isActive
|
import kotlinx.coroutines.isActive
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
@ -17,6 +16,7 @@ import space.kscience.visionforge.VisionClient
|
|||||||
import space.kscience.visionforge.plotly.PlotlyPlugin
|
import space.kscience.visionforge.plotly.PlotlyPlugin
|
||||||
import space.kscience.visionforge.ring.ThreeCanvasWithControls
|
import space.kscience.visionforge.ring.ThreeCanvasWithControls
|
||||||
import space.kscience.visionforge.ring.ThreeWithControlsPlugin
|
import space.kscience.visionforge.ring.ThreeWithControlsPlugin
|
||||||
|
import space.kscience.visionforge.ring.solid
|
||||||
import space.kscience.visionforge.solid.*
|
import space.kscience.visionforge.solid.*
|
||||||
import space.kscience.visionforge.startApplication
|
import space.kscience.visionforge.startApplication
|
||||||
import styled.css
|
import styled.css
|
||||||
@ -38,51 +38,6 @@ private class JsPlaygroundApp : Application {
|
|||||||
|
|
||||||
val bouncingSphereTrace = Trace()
|
val bouncingSphereTrace = Trace()
|
||||||
|
|
||||||
val bouncingSphere = SolidGroup {
|
|
||||||
sphere(5.0, "ball") {
|
|
||||||
detail = 16
|
|
||||||
color("red")
|
|
||||||
val h = 100.0
|
|
||||||
y = h
|
|
||||||
GlobalScope.launch {
|
|
||||||
val g = 10.0
|
|
||||||
val dt = 0.1
|
|
||||||
var time = 0.0
|
|
||||||
var velocity = 0.0
|
|
||||||
while (isActive) {
|
|
||||||
delay(20)
|
|
||||||
time += dt
|
|
||||||
velocity -= g * dt
|
|
||||||
y = y.toDouble() + velocity * dt
|
|
||||||
bouncingSphereTrace.appendXY(time, y)
|
|
||||||
if (y.toDouble() <= 2.5) {
|
|
||||||
//conservation of energy
|
|
||||||
velocity = sqrt(2 * g * h)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
box(200, 5, 200, name = "floor") {
|
|
||||||
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) {
|
render(element) {
|
||||||
styledDiv {
|
styledDiv {
|
||||||
css {
|
css {
|
||||||
@ -94,18 +49,46 @@ private class JsPlaygroundApp : Application {
|
|||||||
SmartTabs("gravity") {
|
SmartTabs("gravity") {
|
||||||
Tab("gravity") {
|
Tab("gravity") {
|
||||||
styledDiv {
|
styledDiv {
|
||||||
css{
|
css {
|
||||||
height = 50.vh
|
height = 50.vh
|
||||||
}
|
}
|
||||||
child(ThreeCanvasWithControls) {
|
child(ThreeCanvasWithControls) {
|
||||||
attrs {
|
attrs {
|
||||||
context = playgroundContext
|
context = playgroundContext
|
||||||
solid = bouncingSphere
|
solid {
|
||||||
|
sphere(5.0, "ball") {
|
||||||
|
detail = 16
|
||||||
|
color("red")
|
||||||
|
val h = 100.0
|
||||||
|
y = h
|
||||||
|
launch {
|
||||||
|
val g = 10.0
|
||||||
|
val dt = 0.1
|
||||||
|
var time = 0.0
|
||||||
|
var velocity = 0.0
|
||||||
|
while (isActive) {
|
||||||
|
delay(20)
|
||||||
|
time += dt
|
||||||
|
velocity -= g * dt
|
||||||
|
y = y.toDouble() + velocity * dt
|
||||||
|
bouncingSphereTrace.appendXY(time, y)
|
||||||
|
if (y.toDouble() <= 2.5) {
|
||||||
|
//conservation of energy
|
||||||
|
velocity = sqrt(2 * g * h)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
box(200, 5, 200, name = "floor") {
|
||||||
|
y = -2.5
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
styledDiv {
|
styledDiv {
|
||||||
css{
|
css {
|
||||||
height = 40.vh
|
height = 40.vh
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -129,10 +112,28 @@ private class JsPlaygroundApp : Application {
|
|||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
Tab("spheres") {
|
Tab("spheres") {
|
||||||
child(ThreeCanvasWithControls) {
|
styledDiv {
|
||||||
attrs {
|
css {
|
||||||
context = playgroundContext
|
height = 90.vh
|
||||||
solid = visionOfSpheres
|
}
|
||||||
|
child(ThreeCanvasWithControls) {
|
||||||
|
val random = Random(112233)
|
||||||
|
attrs {
|
||||||
|
context = playgroundContext
|
||||||
|
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
|
package space.kscience.visionforge.ring
|
||||||
|
|
||||||
|
import kotlinx.coroutines.Deferred
|
||||||
|
import kotlinx.coroutines.async
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.css.*
|
import kotlinx.css.*
|
||||||
import react.*
|
import react.*
|
||||||
import react.dom.div
|
import react.dom.div
|
||||||
import react.dom.span
|
import react.dom.span
|
||||||
import ringui.Island
|
import ringui.*
|
||||||
import ringui.IslandContent
|
|
||||||
import ringui.IslandHeader
|
|
||||||
import ringui.Link
|
|
||||||
import space.kscience.dataforge.context.Context
|
import space.kscience.dataforge.context.Context
|
||||||
import space.kscience.dataforge.names.Name
|
import space.kscience.dataforge.names.Name
|
||||||
import space.kscience.dataforge.names.NameToken
|
import space.kscience.dataforge.names.NameToken
|
||||||
import space.kscience.dataforge.names.isEmpty
|
import space.kscience.dataforge.names.isEmpty
|
||||||
import space.kscience.dataforge.names.length
|
import space.kscience.dataforge.names.length
|
||||||
|
import space.kscience.visionforge.Vision
|
||||||
import space.kscience.visionforge.VisionGroup
|
import space.kscience.visionforge.VisionGroup
|
||||||
import space.kscience.visionforge.computeProperties
|
import space.kscience.visionforge.computeProperties
|
||||||
import space.kscience.visionforge.react.ThreeCanvasComponent
|
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.flexRow
|
||||||
import space.kscience.visionforge.react.propertyEditor
|
import space.kscience.visionforge.react.propertyEditor
|
||||||
import space.kscience.visionforge.solid.Solid
|
import space.kscience.visionforge.solid.Solid
|
||||||
|
import space.kscience.visionforge.solid.SolidGroup
|
||||||
import space.kscience.visionforge.solid.specifications.Canvas3DOptions
|
import space.kscience.visionforge.solid.specifications.Canvas3DOptions
|
||||||
import styled.css
|
import styled.css
|
||||||
import styled.styledDiv
|
import styled.styledDiv
|
||||||
|
|
||||||
public external interface ThreeCanvasWithControlsProps : RProps {
|
public external interface ThreeCanvasWithControlsProps : RProps {
|
||||||
public var context: Context
|
public var context: Context
|
||||||
public var solid: Solid?
|
public var builderOfSolid: Deferred<Solid?>
|
||||||
public var selected: Name?
|
public var selected: Name?
|
||||||
public var additionalTabs: Map<String, RBuilder.() -> Unit>?
|
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) {
|
public fun ThreeCanvasWithControlsProps.tab(title: String, block: RBuilder.() -> Unit) {
|
||||||
additionalTabs = (additionalTabs ?: emptyMap()) + (title to block)
|
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> =
|
public val ThreeCanvasWithControls: FunctionComponent<ThreeCanvasWithControlsProps> =
|
||||||
functionalComponent("ThreeViewWithControls") { props ->
|
functionalComponent("ThreeViewWithControls") { props ->
|
||||||
var selected by useState { props.selected }
|
var selected by useState { props.selected }
|
||||||
|
var solid: Solid? by useState(null)
|
||||||
|
|
||||||
|
useEffect {
|
||||||
|
props.context.launch {
|
||||||
|
solid = props.builderOfSolid.await()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
val onSelect: (Name?) -> Unit = {
|
val onSelect: (Name?) -> Unit = {
|
||||||
selected = it
|
selected = it
|
||||||
@ -83,15 +98,16 @@ public val ThreeCanvasWithControls: FunctionComponent<ThreeCanvasWithControlsPro
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val selectedVision = useMemo(selected) {
|
val selectedVision: Vision? = useMemo(props.builderOfSolid, selected) {
|
||||||
selected?.let {
|
selected?.let {
|
||||||
when {
|
when {
|
||||||
it.isEmpty() -> props.solid
|
it.isEmpty() -> solid
|
||||||
else -> (props.solid as? VisionGroup)?.get(it)
|
else -> (solid as? VisionGroup)?.get(it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
flexRow {
|
flexRow {
|
||||||
css {
|
css {
|
||||||
height = 100.pct
|
height = 100.pct
|
||||||
@ -108,12 +124,20 @@ public val ThreeCanvasWithControls: FunctionComponent<ThreeCanvasWithControlsPro
|
|||||||
position = Position.relative
|
position = Position.relative
|
||||||
}
|
}
|
||||||
|
|
||||||
child(ThreeCanvasComponent) {
|
if (solid == null) {
|
||||||
attrs {
|
LoaderScreen {
|
||||||
this.context = props.context
|
attrs {
|
||||||
this.solid = props.solid
|
message = "Loading Three vision"
|
||||||
this.selected = selected
|
}
|
||||||
this.options = options
|
}
|
||||||
|
} else {
|
||||||
|
child(ThreeCanvasComponent) {
|
||||||
|
attrs {
|
||||||
|
this.context = props.context
|
||||||
|
this.solid = solid
|
||||||
|
this.selected = selected
|
||||||
|
this.options = options
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -150,7 +174,8 @@ public val ThreeCanvasWithControls: FunctionComponent<ThreeCanvasWithControlsPro
|
|||||||
minWidth = 400.px
|
minWidth = 400.px
|
||||||
flex(1.0, 10.0, FlexBasis("300px"))
|
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
|
package space.kscience.visionforge.ring
|
||||||
|
|
||||||
|
import kotlinx.coroutines.async
|
||||||
import org.w3c.dom.Element
|
import org.w3c.dom.Element
|
||||||
import react.child
|
import react.child
|
||||||
import space.kscience.dataforge.context.AbstractPlugin
|
import space.kscience.dataforge.context.AbstractPlugin
|
||||||
@ -28,7 +29,7 @@ public class ThreeWithControlsPlugin : AbstractPlugin(), ElementVisionRenderer {
|
|||||||
child(ThreeCanvasWithControls) {
|
child(ThreeCanvasWithControls) {
|
||||||
attrs {
|
attrs {
|
||||||
this.context = this@ThreeWithControlsPlugin.context
|
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
|
package space.kscience.visionforge
|
||||||
|
|
||||||
import kotlinx.browser.document
|
import kotlinx.browser.document
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.dom.hasClass
|
import kotlinx.dom.hasClass
|
||||||
|
import kotlin.coroutines.CoroutineContext
|
||||||
|
import kotlin.coroutines.EmptyCoroutineContext
|
||||||
|
|
||||||
|
|
||||||
public external val module: Module
|
public external val module: Module
|
||||||
@ -25,7 +28,10 @@ public external interface Module {
|
|||||||
*
|
*
|
||||||
* Base interface for applications supporting Hot Module Replacement (HMR).
|
* 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.
|
* Starting point for an application.
|
||||||
* @param state Initial state between Hot Module Replacement (HMR).
|
* @param state Initial state between Hot Module Replacement (HMR).
|
||||||
|
Loading…
Reference in New Issue
Block a user