Finish ThreeCancas encapsulation
This commit is contained in:
parent
359eb05f83
commit
288307eaa8
@ -11,7 +11,6 @@ import space.kscience.dataforge.context.fetch
|
|||||||
import space.kscience.dataforge.names.Name
|
import space.kscience.dataforge.names.Name
|
||||||
import space.kscience.gdml.Gdml
|
import space.kscience.gdml.Gdml
|
||||||
import space.kscience.gdml.decodeFromString
|
import space.kscience.gdml.decodeFromString
|
||||||
import space.kscience.visionforge.Vision
|
|
||||||
import space.kscience.visionforge.bootstrap.gridRow
|
import space.kscience.visionforge.bootstrap.gridRow
|
||||||
import space.kscience.visionforge.bootstrap.nameCrumbs
|
import space.kscience.visionforge.bootstrap.nameCrumbs
|
||||||
import space.kscience.visionforge.gdml.toVision
|
import space.kscience.visionforge.gdml.toVision
|
||||||
@ -21,27 +20,31 @@ import space.kscience.visionforge.ring.ringThreeControls
|
|||||||
import space.kscience.visionforge.solid.Solid
|
import space.kscience.visionforge.solid.Solid
|
||||||
import space.kscience.visionforge.solid.Solids
|
import space.kscience.visionforge.solid.Solids
|
||||||
import space.kscience.visionforge.solid.specifications.Canvas3DOptions
|
import space.kscience.visionforge.solid.specifications.Canvas3DOptions
|
||||||
import space.kscience.visionforge.solid.three.ThreeCanvas
|
|
||||||
import styled.css
|
import styled.css
|
||||||
import styled.styledDiv
|
import styled.styledDiv
|
||||||
|
|
||||||
external interface GDMLAppProps : RProps {
|
external interface GDMLAppProps : RProps {
|
||||||
var context: Context
|
var context: Context
|
||||||
var rootVision: Vision?
|
var vision: Solid?
|
||||||
var selected: Name?
|
var selected: Name?
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsExport
|
@JsExport
|
||||||
val GDMLApp = functionalComponent<GDMLAppProps>("GDMLApp") { props ->
|
val GDMLApp = functionalComponent<GDMLAppProps>("GDMLApp") { props ->
|
||||||
var selected by useState { props.selected }
|
var selected by useState { props.selected }
|
||||||
var canvas: ThreeCanvas? by useState { null }
|
var vision: Solid? by useState { props.vision }
|
||||||
var vision: Vision? by useState { props.rootVision }
|
|
||||||
|
|
||||||
val onSelect: (Name?) -> Unit = {
|
val onSelect: (Name?) -> Unit = {
|
||||||
selected = it
|
selected = it
|
||||||
}
|
}
|
||||||
|
|
||||||
val visionManager = useMemo({ props.context.fetch(Solids).visionManager }, arrayOf(props.context))
|
val options = useMemo {
|
||||||
|
Canvas3DOptions.invoke {
|
||||||
|
this.onSelect = onSelect
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val visionManager = useMemo(props.context) { props.context.fetch(Solids).visionManager }
|
||||||
|
|
||||||
fun loadData(name: String, data: String) {
|
fun loadData(name: String, data: String) {
|
||||||
val parsedVision = when {
|
val parsedVision = when {
|
||||||
@ -56,7 +59,7 @@ val GDMLApp = functionalComponent<GDMLAppProps>("GDMLApp") { props ->
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
vision = parsedVision
|
vision = parsedVision as? Solid ?: error("Parsed vision is not a solid")
|
||||||
}
|
}
|
||||||
|
|
||||||
gridRow {
|
gridRow {
|
||||||
@ -78,14 +81,9 @@ val GDMLApp = functionalComponent<GDMLAppProps>("GDMLApp") { props ->
|
|||||||
child(ThreeCanvasComponent) {
|
child(ThreeCanvasComponent) {
|
||||||
attrs {
|
attrs {
|
||||||
this.context = props.context
|
this.context = props.context
|
||||||
this.obj = vision as? Solid
|
this.obj = vision
|
||||||
this.selected = selected
|
this.selected = selected
|
||||||
this.options = Canvas3DOptions.invoke {
|
this.options = options
|
||||||
this.onSelect = onSelect
|
|
||||||
}
|
|
||||||
this.canvasCallback = {
|
|
||||||
canvas = it
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -111,9 +109,7 @@ val GDMLApp = functionalComponent<GDMLAppProps>("GDMLApp") { props ->
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
canvas?.let {
|
ringThreeControls(options, props.vision, selected, onSelect)
|
||||||
ringThreeControls(it, selected, onSelect)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -29,7 +29,7 @@ private class GDMLDemoApp : Application {
|
|||||||
//println(context.plugins.fetch(VisionManager).encodeToString(vision))
|
//println(context.plugins.fetch(VisionManager).encodeToString(vision))
|
||||||
attrs {
|
attrs {
|
||||||
this.context = context
|
this.context = context
|
||||||
this.rootVision = vision
|
this.vision = vision
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,11 +6,8 @@ import kotlinx.coroutines.GlobalScope
|
|||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.css.*
|
import kotlinx.css.*
|
||||||
import kotlinx.html.js.onClickFunction
|
import kotlinx.html.js.onClickFunction
|
||||||
import react.RProps
|
import react.*
|
||||||
import react.child
|
|
||||||
import react.dom.*
|
import react.dom.*
|
||||||
import react.functionalComponent
|
|
||||||
import react.useState
|
|
||||||
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
|
||||||
@ -26,7 +23,6 @@ import space.kscience.visionforge.react.flexColumn
|
|||||||
import space.kscience.visionforge.react.objectTree
|
import space.kscience.visionforge.react.objectTree
|
||||||
import space.kscience.visionforge.solid.specifications.Camera
|
import space.kscience.visionforge.solid.specifications.Camera
|
||||||
import space.kscience.visionforge.solid.specifications.Canvas3DOptions
|
import space.kscience.visionforge.solid.specifications.Canvas3DOptions
|
||||||
import space.kscience.visionforge.solid.three.ThreeCanvas
|
|
||||||
import styled.css
|
import styled.css
|
||||||
import styled.styledDiv
|
import styled.styledDiv
|
||||||
import kotlin.math.PI
|
import kotlin.math.PI
|
||||||
@ -49,12 +45,17 @@ private val canvasConfig = Canvas3DOptions {
|
|||||||
@JsExport
|
@JsExport
|
||||||
val MMApp = functionalComponent<MMAppProps>("Muon monitor") { props ->
|
val MMApp = functionalComponent<MMAppProps>("Muon monitor") { props ->
|
||||||
var selected by useState { props.selected }
|
var selected by useState { props.selected }
|
||||||
var canvas: ThreeCanvas? by useState { null }
|
|
||||||
|
|
||||||
val onSelect: (Name?) -> Unit = {
|
val onSelect: (Name?) -> Unit = {
|
||||||
selected = it
|
selected = it
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val options = useMemo {
|
||||||
|
Canvas3DOptions.invoke {
|
||||||
|
this.onSelect = onSelect
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
val root = props.model.root
|
val root = props.model.root
|
||||||
|
|
||||||
gridRow {
|
gridRow {
|
||||||
@ -95,9 +96,6 @@ val MMApp = functionalComponent<MMAppProps>("Muon monitor") { props ->
|
|||||||
this.options = canvasConfig.apply {
|
this.options = canvasConfig.apply {
|
||||||
this.onSelect = onSelect
|
this.onSelect = onSelect
|
||||||
}
|
}
|
||||||
this.canvasCallback = {
|
|
||||||
canvas = it
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -113,11 +111,10 @@ val MMApp = functionalComponent<MMAppProps>("Muon monitor") { props ->
|
|||||||
flex(0.0, 1.0, FlexBasis.zero)
|
flex(0.0, 1.0, FlexBasis.zero)
|
||||||
}
|
}
|
||||||
//settings
|
//settings
|
||||||
canvas?.let {
|
|
||||||
card("Canvas configuration") {
|
card("Canvas configuration") {
|
||||||
canvasControls(it)
|
canvasControls(options, root)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
card("Events") {
|
card("Events") {
|
||||||
button {
|
button {
|
||||||
+"Next"
|
+"Next"
|
||||||
|
@ -19,7 +19,6 @@ import space.kscience.visionforge.VisionLayout
|
|||||||
import space.kscience.visionforge.solid.Solid
|
import space.kscience.visionforge.solid.Solid
|
||||||
import space.kscience.visionforge.solid.three.ThreeCanvas
|
import space.kscience.visionforge.solid.three.ThreeCanvas
|
||||||
import space.kscience.visionforge.solid.three.ThreePlugin
|
import space.kscience.visionforge.solid.three.ThreePlugin
|
||||||
import space.kscience.visionforge.solid.three.configure
|
|
||||||
|
|
||||||
class ThreeDemoGrid(element: Element) : VisionLayout<Solid> {
|
class ThreeDemoGrid(element: Element) : VisionLayout<Solid> {
|
||||||
private lateinit var navigationElement: HTMLElement
|
private lateinit var navigationElement: HTMLElement
|
||||||
@ -71,7 +70,7 @@ class ThreeDemoGrid(element: Element) : VisionLayout<Solid> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
val element = document.getElementById("output-$name") ?: error("Element not found")
|
val element = document.getElementById("output-$name") ?: error("Element not found")
|
||||||
three.getOrCreateCanvas(element).also { it.configure(canvasOptions) }
|
three.getOrCreateCanvas(element, canvasOptions)
|
||||||
}.render(vision)
|
}.render(vision)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,12 +13,11 @@ import react.*
|
|||||||
import react.dom.attrs
|
import react.dom.attrs
|
||||||
import react.dom.button
|
import react.dom.button
|
||||||
import space.kscience.dataforge.meta.withDefault
|
import space.kscience.dataforge.meta.withDefault
|
||||||
|
import space.kscience.visionforge.Vision
|
||||||
import space.kscience.visionforge.react.flexColumn
|
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.SolidGroup
|
|
||||||
import space.kscience.visionforge.solid.specifications.Canvas3DOptions
|
import space.kscience.visionforge.solid.specifications.Canvas3DOptions
|
||||||
import space.kscience.visionforge.solid.three.ThreeCanvas
|
|
||||||
import styled.css
|
import styled.css
|
||||||
|
|
||||||
private fun saveData(event: Event, fileName: String, mimeType: String = "text/plain", dataBuilder: () -> String) {
|
private fun saveData(event: Event, fileName: String, mimeType: String = "text/plain", dataBuilder: () -> String) {
|
||||||
@ -30,37 +29,33 @@ private fun saveData(event: Event, fileName: String, mimeType: String = "text/pl
|
|||||||
fileSaver.saveAs(blob, fileName)
|
fileSaver.saveAs(blob, fileName)
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun RBuilder.canvasControls(canvas: ThreeCanvas): ReactElement {
|
public fun RBuilder.canvasControls(canvasOptions: Canvas3DOptions, vision: Vision?): ReactElement {
|
||||||
return child(CanvasControls) {
|
return child(CanvasControls) {
|
||||||
attrs {
|
attrs {
|
||||||
this.canvas = canvas
|
this.canvasOptions = canvasOptions
|
||||||
|
this.vision = vision
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public external interface CanvasControlsProps : RProps {
|
public external interface CanvasControlsProps : RProps {
|
||||||
public var canvas: ThreeCanvas
|
public var canvasOptions: Canvas3DOptions
|
||||||
|
public var vision: Vision?
|
||||||
}
|
}
|
||||||
|
|
||||||
public val CanvasControls: FunctionalComponent<CanvasControlsProps> = functionalComponent("CanvasControls") { props ->
|
public val CanvasControls: FunctionalComponent<CanvasControlsProps> = functionalComponent("CanvasControls") { props ->
|
||||||
val visionManager = useMemo(
|
|
||||||
{ props.canvas.three.solids.visionManager },
|
|
||||||
arrayOf(props.canvas)
|
|
||||||
)
|
|
||||||
flexColumn {
|
flexColumn {
|
||||||
flexRow {
|
flexRow {
|
||||||
css {
|
css {
|
||||||
border(1.px, BorderStyle.solid, Color.blue)
|
border(1.px, BorderStyle.solid, Color.blue)
|
||||||
padding(4.px)
|
padding(4.px)
|
||||||
}
|
}
|
||||||
|
props.vision?.manager?.let { manager ->
|
||||||
button {
|
button {
|
||||||
+"Export"
|
+"Export"
|
||||||
attrs {
|
attrs {
|
||||||
onClickFunction = {
|
onClickFunction = {
|
||||||
val json = (props.canvas.content as? SolidGroup)?.let { group ->
|
val json = manager.encodeToString(props.vision!!)
|
||||||
visionManager.encodeToString(group)
|
|
||||||
}
|
|
||||||
if (json != null) {
|
|
||||||
saveData(it, "object.json", "text/json") {
|
saveData(it, "object.json", "text/json") {
|
||||||
json
|
json
|
||||||
}
|
}
|
||||||
@ -70,8 +65,8 @@ public val CanvasControls: FunctionalComponent<CanvasControlsProps> = functional
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
propertyEditor(
|
propertyEditor(
|
||||||
ownProperties = props.canvas.options,
|
ownProperties = props.canvasOptions,
|
||||||
allProperties = props.canvas.options.withDefault(Canvas3DOptions.descriptor.defaultMeta),
|
allProperties = props.canvasOptions.withDefault(Canvas3DOptions.descriptor.defaultMeta),
|
||||||
descriptor = Canvas3DOptions.descriptor,
|
descriptor = Canvas3DOptions.descriptor,
|
||||||
expanded = false
|
expanded = false
|
||||||
)
|
)
|
||||||
|
@ -9,23 +9,23 @@ import space.kscience.dataforge.names.isEmpty
|
|||||||
import space.kscience.visionforge.Vision
|
import space.kscience.visionforge.Vision
|
||||||
import space.kscience.visionforge.VisionGroup
|
import space.kscience.visionforge.VisionGroup
|
||||||
import space.kscience.visionforge.react.objectTree
|
import space.kscience.visionforge.react.objectTree
|
||||||
import space.kscience.visionforge.solid.three.ThreeCanvas
|
import space.kscience.visionforge.solid.specifications.Canvas3DOptions
|
||||||
import styled.css
|
import styled.css
|
||||||
import styled.styledDiv
|
import styled.styledDiv
|
||||||
|
|
||||||
public external interface ThreeControlsProps : RProps {
|
public external interface ThreeControlsProps : RProps {
|
||||||
public var canvas: ThreeCanvas
|
public var canvasOptions: Canvas3DOptions
|
||||||
|
public var vision: Vision?
|
||||||
public var selected: Name?
|
public var selected: Name?
|
||||||
public var onSelect: (Name) -> Unit
|
public var onSelect: (Name) -> Unit
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsExport
|
@JsExport
|
||||||
public val ThreeControls: FunctionalComponent<ThreeControlsProps> = functionalComponent { props ->
|
public val ThreeControls: FunctionalComponent<ThreeControlsProps> = functionalComponent { props ->
|
||||||
val vision = props.canvas.content
|
|
||||||
tabPane(if (props.selected != null) "Properties" else null) {
|
tabPane(if (props.selected != null) "Properties" else null) {
|
||||||
tab("Canvas") {
|
tab("Canvas") {
|
||||||
card("Canvas configuration") {
|
card("Canvas configuration") {
|
||||||
canvasControls(props.canvas)
|
canvasControls(props.canvasOptions, props.vision)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
tab("Tree") {
|
tab("Tree") {
|
||||||
@ -38,7 +38,7 @@ public val ThreeControls: FunctionalComponent<ThreeControlsProps> = functionalCo
|
|||||||
css {
|
css {
|
||||||
flex(1.0, 1.0, FlexBasis.inherit)
|
flex(1.0, 1.0, FlexBasis.inherit)
|
||||||
}
|
}
|
||||||
props.canvas.content?.let {
|
props.vision?.let {
|
||||||
objectTree(it, props.selected, props.onSelect)
|
objectTree(it, props.selected, props.onSelect)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -47,8 +47,8 @@ public val ThreeControls: FunctionalComponent<ThreeControlsProps> = functionalCo
|
|||||||
props.selected.let { selected ->
|
props.selected.let { selected ->
|
||||||
val selectedObject: Vision? = when {
|
val selectedObject: Vision? = when {
|
||||||
selected == null -> null
|
selected == null -> null
|
||||||
selected.isEmpty() -> vision
|
selected.isEmpty() -> props.vision
|
||||||
else -> (vision as? VisionGroup)?.get(selected)
|
else -> (props.vision as? VisionGroup)?.get(selected)
|
||||||
}
|
}
|
||||||
if (selectedObject != null) {
|
if (selectedObject != null) {
|
||||||
visionPropertyEditor(selectedObject, key = selected)
|
visionPropertyEditor(selectedObject, key = selected)
|
||||||
@ -62,13 +62,15 @@ public val ThreeControls: FunctionalComponent<ThreeControlsProps> = functionalCo
|
|||||||
}
|
}
|
||||||
|
|
||||||
public fun RBuilder.threeControls(
|
public fun RBuilder.threeControls(
|
||||||
canvas: ThreeCanvas,
|
canvasOptions: Canvas3DOptions,
|
||||||
|
vision: Vision?,
|
||||||
selected: Name?,
|
selected: Name?,
|
||||||
onSelect: (Name) -> Unit = {},
|
onSelect: (Name) -> Unit = {},
|
||||||
builder: TabBuilder.() -> Unit = {},
|
builder: TabBuilder.() -> Unit = {},
|
||||||
): ReactElement = child(ThreeControls) {
|
): ReactElement = child(ThreeControls) {
|
||||||
attrs {
|
attrs {
|
||||||
this.canvas = canvas
|
this.canvasOptions = canvasOptions
|
||||||
|
this.vision = vision
|
||||||
this.selected = selected
|
this.selected = selected
|
||||||
this.onSelect = onSelect
|
this.onSelect = onSelect
|
||||||
}
|
}
|
||||||
|
@ -14,16 +14,14 @@ import space.kscience.visionforge.solid.Solid
|
|||||||
import space.kscience.visionforge.solid.specifications.Canvas3DOptions
|
import space.kscience.visionforge.solid.specifications.Canvas3DOptions
|
||||||
import space.kscience.visionforge.solid.three.ThreeCanvas
|
import space.kscience.visionforge.solid.three.ThreeCanvas
|
||||||
import space.kscience.visionforge.solid.three.ThreePlugin
|
import space.kscience.visionforge.solid.three.ThreePlugin
|
||||||
import space.kscience.visionforge.solid.three.configure
|
|
||||||
import styled.css
|
import styled.css
|
||||||
import styled.styledDiv
|
import styled.styledDiv
|
||||||
|
|
||||||
public external interface ThreeCanvasProps : RProps {
|
public external interface ThreeCanvasProps : RProps {
|
||||||
public var context: Context
|
public var context: Context
|
||||||
|
public var options: Canvas3DOptions
|
||||||
public var obj: Solid?
|
public var obj: Solid?
|
||||||
public var options: Canvas3DOptions?
|
|
||||||
public var selected: Name?
|
public var selected: Name?
|
||||||
public var canvasCallback: ((ThreeCanvas?) -> Unit)?
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public external interface ThreeCanvasState : RState {
|
public external interface ThreeCanvasState : RState {
|
||||||
@ -42,22 +40,15 @@ public val ThreeCanvasComponent: FunctionalComponent<ThreeCanvasProps> = functio
|
|||||||
useEffect(listOf(props.obj, props.options, elementRef)) {
|
useEffect(listOf(props.obj, props.options, elementRef)) {
|
||||||
if (canvas == null) {
|
if (canvas == null) {
|
||||||
val element = elementRef.current as? HTMLElement ?: error("Canvas element not found")
|
val element = elementRef.current as? HTMLElement ?: error("Canvas element not found")
|
||||||
val newCanvas: ThreeCanvas = three.getOrCreateCanvas(element)
|
canvas = three.getOrCreateCanvas(element, props.options)
|
||||||
props.options?.let {
|
|
||||||
newCanvas.configure(it)
|
|
||||||
}
|
|
||||||
props.canvasCallback?.invoke(newCanvas)
|
|
||||||
canvas = newCanvas
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
useEffect(listOf(canvas, props.obj)) {
|
useEffect(listOf(canvas, props.obj)) {
|
||||||
props.obj?.let { obj ->
|
props.obj?.let { obj ->
|
||||||
if (canvas?.content != obj) {
|
|
||||||
canvas?.render(obj)
|
canvas?.render(obj)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
useEffect(listOf(canvas, props.selected)) {
|
useEffect(listOf(canvas, props.selected)) {
|
||||||
canvas?.select(props.selected)
|
canvas?.select(props.selected)
|
||||||
|
@ -1,10 +1,7 @@
|
|||||||
package space.kscience.visionforge.ring
|
package space.kscience.visionforge.ring
|
||||||
|
|
||||||
import kotlinx.css.*
|
import kotlinx.css.*
|
||||||
import react.RProps
|
import react.*
|
||||||
import react.child
|
|
||||||
import react.functionalComponent
|
|
||||||
import react.useState
|
|
||||||
import ringui.grid.ringCol
|
import ringui.grid.ringCol
|
||||||
import ringui.grid.ringGrid
|
import ringui.grid.ringGrid
|
||||||
import ringui.grid.ringRow
|
import ringui.grid.ringRow
|
||||||
@ -14,25 +11,27 @@ import space.kscience.visionforge.Vision
|
|||||||
import space.kscience.visionforge.react.ThreeCanvasComponent
|
import space.kscience.visionforge.react.ThreeCanvasComponent
|
||||||
import space.kscience.visionforge.solid.Solid
|
import space.kscience.visionforge.solid.Solid
|
||||||
import space.kscience.visionforge.solid.specifications.Canvas3DOptions
|
import space.kscience.visionforge.solid.specifications.Canvas3DOptions
|
||||||
import space.kscience.visionforge.solid.three.ThreeCanvas
|
|
||||||
import styled.css
|
import styled.css
|
||||||
import styled.styledDiv
|
import styled.styledDiv
|
||||||
|
|
||||||
public external interface GdmlViewProps : RProps {
|
public external interface ThreeWithControlsProps : RProps {
|
||||||
public var context: Context
|
public var context: Context
|
||||||
public var rootVision: Vision?
|
public var vision: Vision?
|
||||||
public var selected: Name?
|
public var selected: Name?
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsExport
|
@JsExport
|
||||||
public val ThreeViewWithControls: (props: GdmlViewProps) -> dynamic =
|
public val ThreeViewWithControls: (props: ThreeWithControlsProps) -> dynamic =
|
||||||
functionalComponent<GdmlViewProps>("ThreeViewWithControls") { props ->
|
functionalComponent("ThreeViewWithControls") { props ->
|
||||||
var selected by useState { props.selected }
|
var selected by useState { props.selected }
|
||||||
var canvas: ThreeCanvas? by useState { null }
|
|
||||||
|
|
||||||
val onSelect: (Name?) -> Unit = {
|
val onSelect: (Name?) -> Unit = {
|
||||||
selected = it
|
selected = it
|
||||||
}
|
}
|
||||||
|
val options = useMemo {
|
||||||
|
Canvas3DOptions.invoke {
|
||||||
|
this.onSelect = onSelect
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
styledDiv {
|
styledDiv {
|
||||||
css {
|
css {
|
||||||
@ -50,14 +49,9 @@ public val ThreeViewWithControls: (props: GdmlViewProps) -> dynamic =
|
|||||||
child(ThreeCanvasComponent) {
|
child(ThreeCanvasComponent) {
|
||||||
attrs {
|
attrs {
|
||||||
this.context = props.context
|
this.context = props.context
|
||||||
this.obj = props.rootVision as? Solid
|
this.obj = props.vision as? Solid
|
||||||
this.selected = selected
|
this.selected = selected
|
||||||
this.options = Canvas3DOptions.invoke {
|
this.options = options
|
||||||
this.onSelect = onSelect
|
|
||||||
}
|
|
||||||
this.canvasCallback = {
|
|
||||||
canvas = it
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -76,9 +70,7 @@ public val ThreeViewWithControls: (props: GdmlViewProps) -> dynamic =
|
|||||||
height = 100.pct
|
height = 100.pct
|
||||||
overflowY = Overflow.auto
|
overflowY = Overflow.auto
|
||||||
}
|
}
|
||||||
canvas?.let {
|
ringThreeControls(options, props.vision, selected, onSelect)
|
||||||
ringThreeControls(it, selected, onSelect)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -28,7 +28,7 @@ public class ThreeWithControls : AbstractPlugin(), ElementVisionRenderer {
|
|||||||
child(ThreeViewWithControls) {
|
child(ThreeViewWithControls) {
|
||||||
attrs {
|
attrs {
|
||||||
this.context = this@ThreeWithControls.context
|
this.context = this@ThreeWithControls.context
|
||||||
this.rootVision = vision
|
this.vision = vision
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,13 +18,12 @@ import space.kscience.dataforge.names.Name
|
|||||||
import space.kscience.dataforge.names.isEmpty
|
import space.kscience.dataforge.names.isEmpty
|
||||||
import space.kscience.visionforge.Vision
|
import space.kscience.visionforge.Vision
|
||||||
import space.kscience.visionforge.VisionGroup
|
import space.kscience.visionforge.VisionGroup
|
||||||
|
import space.kscience.visionforge.encodeToString
|
||||||
import space.kscience.visionforge.react.flexColumn
|
import space.kscience.visionforge.react.flexColumn
|
||||||
import space.kscience.visionforge.react.flexRow
|
import space.kscience.visionforge.react.flexRow
|
||||||
import space.kscience.visionforge.react.objectTree
|
import space.kscience.visionforge.react.objectTree
|
||||||
import space.kscience.visionforge.react.propertyEditor
|
import space.kscience.visionforge.react.propertyEditor
|
||||||
import space.kscience.visionforge.solid.SolidGroup
|
|
||||||
import space.kscience.visionforge.solid.specifications.Canvas3DOptions
|
import space.kscience.visionforge.solid.specifications.Canvas3DOptions
|
||||||
import space.kscience.visionforge.solid.three.ThreeCanvas
|
|
||||||
import styled.css
|
import styled.css
|
||||||
import styled.styledDiv
|
import styled.styledDiv
|
||||||
|
|
||||||
@ -37,48 +36,45 @@ internal fun saveData(event: Event, fileName: String, mimeType: String = "text/p
|
|||||||
fileSaver.saveAs(blob, fileName)
|
fileSaver.saveAs(blob, fileName)
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun RBuilder.canvasControls(canvas: ThreeCanvas): ReactElement {
|
internal fun RBuilder.canvasControls(options: Canvas3DOptions, vision: Vision?): ReactElement {
|
||||||
return child(CanvasControls) {
|
return child(CanvasControls) {
|
||||||
attrs {
|
attrs {
|
||||||
this.canvas = canvas
|
this.options = options
|
||||||
|
this.vision = vision
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal external interface CanvasControlsProps : RProps {
|
internal external interface CanvasControlsProps : RProps {
|
||||||
public var canvas: ThreeCanvas
|
public var options: Canvas3DOptions
|
||||||
|
public var vision: Vision?
|
||||||
}
|
}
|
||||||
|
|
||||||
internal val CanvasControls: FunctionalComponent<CanvasControlsProps> = functionalComponent("CanvasControls") { props ->
|
internal val CanvasControls: FunctionalComponent<CanvasControlsProps> = functionalComponent("CanvasControls") { props ->
|
||||||
val visionManager = useMemo(
|
|
||||||
{ props.canvas.three.solids.visionManager },
|
|
||||||
arrayOf(props.canvas)
|
|
||||||
)
|
|
||||||
flexColumn {
|
flexColumn {
|
||||||
flexRow {
|
flexRow {
|
||||||
css {
|
css {
|
||||||
border(1.px, BorderStyle.solid, Color.blue)
|
border(1.px, BorderStyle.solid, Color.blue)
|
||||||
padding(4.px)
|
padding(4.px)
|
||||||
}
|
}
|
||||||
|
props.vision?.let { vision ->
|
||||||
button {
|
button {
|
||||||
+"Export"
|
+"Export"
|
||||||
attrs {
|
attrs {
|
||||||
onClickFunction = {
|
onClickFunction = {
|
||||||
val json = (props.canvas.content as? SolidGroup)?.let { group ->
|
val json = vision.encodeToString()
|
||||||
visionManager.encodeToString(group)
|
|
||||||
}
|
|
||||||
if (json != null) {
|
|
||||||
saveData(it, "object.json", "text/json") {
|
saveData(it, "object.json", "text/json") {
|
||||||
json
|
json
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
propertyEditor(
|
propertyEditor(
|
||||||
ownProperties = props.canvas.options,
|
ownProperties = props.options,
|
||||||
allProperties = props.canvas.options.withDefault(Canvas3DOptions.descriptor.defaultMeta),
|
allProperties = props.options.withDefault(Canvas3DOptions.descriptor.defaultMeta),
|
||||||
descriptor = Canvas3DOptions.descriptor,
|
descriptor = Canvas3DOptions.descriptor,
|
||||||
expanded = false
|
expanded = false
|
||||||
)
|
)
|
||||||
@ -88,18 +84,18 @@ internal val CanvasControls: FunctionalComponent<CanvasControlsProps> = function
|
|||||||
|
|
||||||
|
|
||||||
public external interface ThreeControlsProps : RProps {
|
public external interface ThreeControlsProps : RProps {
|
||||||
public var canvas: ThreeCanvas
|
public var canvasOptions: Canvas3DOptions
|
||||||
|
public var vision: Vision?
|
||||||
public var selected: Name?
|
public var selected: Name?
|
||||||
public var onSelect: (Name) -> Unit
|
public var onSelect: (Name) -> Unit
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsExport
|
@JsExport
|
||||||
public val ThreeControls: FunctionalComponent<ThreeControlsProps> = functionalComponent { props ->
|
public val ThreeControls: FunctionalComponent<ThreeControlsProps> = functionalComponent { props ->
|
||||||
val vision = props.canvas.content
|
|
||||||
ringSmartTabs(if (props.selected != null) "Properties" else null) {
|
ringSmartTabs(if (props.selected != null) "Properties" else null) {
|
||||||
ringTab("Canvas") {
|
ringTab("Canvas") {
|
||||||
ringIsland("Canvas configuration") {
|
ringIsland("Canvas configuration") {
|
||||||
canvasControls(props.canvas)
|
canvasControls(props.canvasOptions, props.vision)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ringTab("Tree") {
|
ringTab("Tree") {
|
||||||
@ -113,7 +109,7 @@ public val ThreeControls: FunctionalComponent<ThreeControlsProps> = functionalCo
|
|||||||
css {
|
css {
|
||||||
flex(1.0, 1.0, FlexBasis.inherit)
|
flex(1.0, 1.0, FlexBasis.inherit)
|
||||||
}
|
}
|
||||||
props.canvas.content?.let {
|
props.vision?.let {
|
||||||
objectTree(it, props.selected, props.onSelect)
|
objectTree(it, props.selected, props.onSelect)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -123,8 +119,8 @@ public val ThreeControls: FunctionalComponent<ThreeControlsProps> = functionalCo
|
|||||||
props.selected.let { selected ->
|
props.selected.let { selected ->
|
||||||
val selectedObject: Vision? = when {
|
val selectedObject: Vision? = when {
|
||||||
selected == null -> null
|
selected == null -> null
|
||||||
selected.isEmpty() -> vision
|
selected.isEmpty() -> props.vision
|
||||||
else -> (vision as? VisionGroup)?.get(selected)
|
else -> (props.vision as? VisionGroup)?.get(selected)
|
||||||
}
|
}
|
||||||
if (selectedObject != null) {
|
if (selectedObject != null) {
|
||||||
ringPropertyEditor(selectedObject, key = selected)
|
ringPropertyEditor(selectedObject, key = selected)
|
||||||
@ -136,13 +132,15 @@ public val ThreeControls: FunctionalComponent<ThreeControlsProps> = functionalCo
|
|||||||
}
|
}
|
||||||
|
|
||||||
public fun RBuilder.ringThreeControls(
|
public fun RBuilder.ringThreeControls(
|
||||||
canvas: ThreeCanvas,
|
canvasOptions: Canvas3DOptions,
|
||||||
|
vision: Vision?,
|
||||||
selected: Name?,
|
selected: Name?,
|
||||||
onSelect: (Name) -> Unit = {},
|
onSelect: (Name) -> Unit = {},
|
||||||
builder: RBuilder.() -> Unit = {},
|
builder: RBuilder.() -> Unit = {},
|
||||||
): ReactElement = child(ThreeControls) {
|
): ReactElement = child(ThreeControls) {
|
||||||
attrs {
|
attrs {
|
||||||
this.canvas = canvas
|
this.canvasOptions = canvasOptions
|
||||||
|
this.vision = vision
|
||||||
this.selected = selected
|
this.selected = selected
|
||||||
this.onSelect = onSelect
|
this.onSelect = onSelect
|
||||||
}
|
}
|
||||||
|
@ -27,6 +27,9 @@ public interface Vision : Described, CoroutineScope {
|
|||||||
*/
|
*/
|
||||||
public var parent: VisionGroup?
|
public var parent: VisionGroup?
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Owner [VisionManager]. Used to define coroutine scope a serialization
|
||||||
|
*/
|
||||||
public val manager: VisionManager? get() = parent?.manager
|
public val manager: VisionManager? get() = parent?.manager
|
||||||
|
|
||||||
override val coroutineContext: CoroutineContext
|
override val coroutineContext: CoroutineContext
|
||||||
@ -69,7 +72,7 @@ public interface Vision : Described, CoroutineScope {
|
|||||||
/**
|
/**
|
||||||
* Notify all listeners that a property has been changed and should be invalidated
|
* Notify all listeners that a property has been changed and should be invalidated
|
||||||
*/
|
*/
|
||||||
public fun invalidateProperty(propertyName: Name): Unit
|
public fun invalidateProperty(propertyName: Name)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update this vision using a dif represented by [VisionChange].
|
* Update this vision using a dif represented by [VisionChange].
|
||||||
|
@ -92,7 +92,6 @@ public open class VisionBase : Vision {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//TODO check memory consumption for the flow
|
//TODO check memory consumption for the flow
|
||||||
@Transient
|
@Transient
|
||||||
private val propertyInvalidationFlow: MutableSharedFlow<Name> = MutableSharedFlow()
|
private val propertyInvalidationFlow: MutableSharedFlow<Name> = MutableSharedFlow()
|
||||||
|
@ -64,9 +64,15 @@ private fun Vision.isolate(manager: VisionManager): Vision {
|
|||||||
return manager.decodeFromJson(json)
|
return manager.decodeFromJson(json)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param void flag showing that this vision child should be removed
|
||||||
|
* @param vision a new value for vision content
|
||||||
|
* @param properties updated properties
|
||||||
|
* @param children a map of children changed in ths [VisionChange]. If a child to be removed, set [void] flag to true.
|
||||||
|
*/
|
||||||
@Serializable
|
@Serializable
|
||||||
public data class VisionChange(
|
public data class VisionChange(
|
||||||
public val reset: Boolean = false,
|
public val void: Boolean = false,
|
||||||
public val vision: Vision? = null,
|
public val vision: Vision? = null,
|
||||||
@Serializable(MetaSerializer::class) public val properties: Meta? = null,
|
@Serializable(MetaSerializer::class) public val properties: Meta? = null,
|
||||||
public val children: Map<Name, VisionChange>? = null,
|
public val children: Map<Name, VisionChange>? = null,
|
||||||
|
@ -134,7 +134,7 @@ public open class VisionGroupBase(
|
|||||||
override fun update(change: VisionChange) {
|
override fun update(change: VisionChange) {
|
||||||
change.children?.forEach { (name, change) ->
|
change.children?.forEach { (name, change) ->
|
||||||
when {
|
when {
|
||||||
change.reset -> set(name, null)
|
change.void -> set(name, null)
|
||||||
change.vision != null -> set(name, change.vision)
|
change.vision != null -> set(name, change.vision)
|
||||||
else -> get(name)?.update(change)
|
else -> get(name)?.update(change)
|
||||||
}
|
}
|
||||||
|
@ -96,3 +96,6 @@ public abstract class VisionPlugin(meta: Meta = Meta.EMPTY) : AbstractPlugin(met
|
|||||||
* Fetch a [VisionManager] from this plugin or create a child plugin with a [VisionManager]
|
* Fetch a [VisionManager] from this plugin or create a child plugin with a [VisionManager]
|
||||||
*/
|
*/
|
||||||
public val Context.visionManager: VisionManager get() = fetch(VisionManager)
|
public val Context.visionManager: VisionManager get() = fetch(VisionManager)
|
||||||
|
|
||||||
|
public fun Vision.encodeToString(): String =
|
||||||
|
manager?.encodeToString(this) ?: error("VisionManager not defined in Vision")
|
@ -39,9 +39,8 @@ import kotlin.math.sin
|
|||||||
*/
|
*/
|
||||||
public class ThreeCanvas(
|
public class ThreeCanvas(
|
||||||
public val three: ThreePlugin,
|
public val three: ThreePlugin,
|
||||||
|
public val options: Canvas3DOptions = Canvas3DOptions()
|
||||||
) {
|
) {
|
||||||
public val options = Canvas3DOptions()
|
|
||||||
|
|
||||||
private var boundingBox: Box3? = null
|
private var boundingBox: Box3? = null
|
||||||
private var root: Object3D? = null
|
private var root: Object3D? = null
|
||||||
set(value) {
|
set(value) {
|
||||||
@ -52,9 +51,6 @@ public class ThreeCanvas(
|
|||||||
private val raycaster = Raycaster()
|
private val raycaster = Raycaster()
|
||||||
private val mousePosition: Vector2 = Vector2()
|
private val mousePosition: Vector2 = Vector2()
|
||||||
|
|
||||||
public var content: Solid? = null
|
|
||||||
private set
|
|
||||||
|
|
||||||
private val scene: Scene = Scene().apply {
|
private val scene: Scene = Scene().apply {
|
||||||
options.useProperty(Canvas3DOptions::axes, this) { axesConfig ->
|
options.useProperty(Canvas3DOptions::axes, this) { axesConfig ->
|
||||||
getObjectByName(AXES_NAME)?.let { remove(it) }
|
getObjectByName(AXES_NAME)?.let { remove(it) }
|
||||||
@ -251,7 +247,6 @@ public class ThreeCanvas(
|
|||||||
val object3D = three.buildObject3D(vision)
|
val object3D = three.buildObject3D(vision)
|
||||||
object3D.name = "@root"
|
object3D.name = "@root"
|
||||||
scene.add(object3D)
|
scene.add(object3D)
|
||||||
content = vision
|
|
||||||
root = object3D
|
root = object3D
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -315,9 +310,9 @@ public class ThreeCanvas(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun ThreeCanvas.configure(options: Canvas3DOptions) {
|
//public fun ThreeCanvas.configure(newOptions: Canvas3DOptions) {
|
||||||
this.options.update(options.toMeta())
|
// this.options.update(newOptions.toMeta())
|
||||||
options.onChange(this) { name, _, newItem ->
|
// options.onChange(this) { name, _, newItem ->
|
||||||
options[name] = newItem
|
// this.options[name] = newItem
|
||||||
}
|
// }
|
||||||
}
|
//}
|
@ -116,9 +116,12 @@ public class ThreePlugin : AbstractPlugin(), ElementVisionRenderer {
|
|||||||
|
|
||||||
public fun getOrCreateCanvas(
|
public fun getOrCreateCanvas(
|
||||||
element: Element,
|
element: Element,
|
||||||
): ThreeCanvas = canvasCache.getOrPut(element){ThreeCanvas(this).apply {
|
options: Canvas3DOptions = Canvas3DOptions(),
|
||||||
|
): ThreeCanvas = canvasCache.getOrPut(element) {
|
||||||
|
ThreeCanvas(this, options).apply {
|
||||||
attach(element)
|
attach(element)
|
||||||
}}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun content(target: String): Map<Name, Any> {
|
override fun content(target: String): Map<Name, Any> {
|
||||||
return when (target) {
|
return when (target) {
|
||||||
|
Loading…
Reference in New Issue
Block a user