From de2ef1dcc5cc2ece398ea2d428e6eaf9709691a1 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Sun, 9 Aug 2020 14:41:24 +0300 Subject: [PATCH 001/151] UI tune-up --- build.gradle.kts | 2 +- .../vision/gdml/demo/GDMLAppComponent.kt | 7 +- .../mipt/npm/muon/monitor/MMAppComponent.kt | 2 +- playground/src/jsMain/kotlin/PlayGroundApp.kt | 2 +- .../vision/bootstrap/MetaViewerComponent.kt | 11 +- .../dataforge/vision/bootstrap/bootstrap.kt | 20 ++++ .../{configEditor.kt => ConfigEditor.kt} | 51 +++------ .../hep/dataforge/vision/react}/ObjectTree.kt | 75 ++++++------ .../hep/dataforge/vision/react/TreeStyles.kt | 83 +++++++++++--- .../dataforge/vision/react/valueChooser.kt | 108 ++++++++---------- 10 files changed, 199 insertions(+), 162 deletions(-) rename ui/react/src/main/kotlin/hep/dataforge/vision/react/{configEditor.kt => ConfigEditor.kt} (82%) rename ui/{bootstrap/src/main/kotlin/hep/dataforge/vision/bootstrap => react/src/main/kotlin/hep/dataforge/vision/react}/ObjectTree.kt (69%) diff --git a/build.gradle.kts b/build.gradle.kts index 56f0b451..f2da0ea9 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -19,7 +19,7 @@ allprojects { } group = "hep.dataforge" - version = "0.1.5-dev" + version = "0.1.5-dev-2" } val githubProject by extra("visionforge") diff --git a/demo/gdml/src/jsMain/kotlin/hep/dataforge/vision/gdml/demo/GDMLAppComponent.kt b/demo/gdml/src/jsMain/kotlin/hep/dataforge/vision/gdml/demo/GDMLAppComponent.kt index ee788190..c189b6b8 100644 --- a/demo/gdml/src/jsMain/kotlin/hep/dataforge/vision/gdml/demo/GDMLAppComponent.kt +++ b/demo/gdml/src/jsMain/kotlin/hep/dataforge/vision/gdml/demo/GDMLAppComponent.kt @@ -7,10 +7,7 @@ import hep.dataforge.vision.Vision import hep.dataforge.vision.VisionGroup import hep.dataforge.vision.bootstrap.* import hep.dataforge.vision.gdml.toVision -import hep.dataforge.vision.react.component -import hep.dataforge.vision.react.configEditor -import hep.dataforge.vision.react.flexColumn -import hep.dataforge.vision.react.state +import hep.dataforge.vision.react.* import hep.dataforge.vision.solid.Solid import hep.dataforge.vision.solid.SolidGroup import hep.dataforge.vision.solid.specifications.Camera @@ -98,7 +95,7 @@ val GDMLApp = component { props -> } } //tree - card("Object tree", "overflow-auto") { + card("Object tree") { visual?.let { objectTree(it, selected, select) } diff --git a/demo/muon-monitor/src/jsMain/kotlin/ru/mipt/npm/muon/monitor/MMAppComponent.kt b/demo/muon-monitor/src/jsMain/kotlin/ru/mipt/npm/muon/monitor/MMAppComponent.kt index 1291efb0..d08788c4 100644 --- a/demo/muon-monitor/src/jsMain/kotlin/ru/mipt/npm/muon/monitor/MMAppComponent.kt +++ b/demo/muon-monitor/src/jsMain/kotlin/ru/mipt/npm/muon/monitor/MMAppComponent.kt @@ -6,9 +6,9 @@ import hep.dataforge.names.NameToken import hep.dataforge.names.isEmpty import hep.dataforge.vision.Vision import hep.dataforge.vision.bootstrap.card -import hep.dataforge.vision.bootstrap.objectTree import hep.dataforge.vision.react.component import hep.dataforge.vision.react.configEditor +import hep.dataforge.vision.react.objectTree import hep.dataforge.vision.react.state import hep.dataforge.vision.solid.specifications.Camera import hep.dataforge.vision.solid.specifications.Canvas3DOptions diff --git a/playground/src/jsMain/kotlin/PlayGroundApp.kt b/playground/src/jsMain/kotlin/PlayGroundApp.kt index c4377c05..3b8a04a4 100644 --- a/playground/src/jsMain/kotlin/PlayGroundApp.kt +++ b/playground/src/jsMain/kotlin/PlayGroundApp.kt @@ -2,8 +2,8 @@ import hep.dataforge.context.Global import hep.dataforge.js.Application import hep.dataforge.js.startApplication import hep.dataforge.names.Name -import hep.dataforge.vision.bootstrap.objectTree import hep.dataforge.vision.bootstrap.visualPropertyEditor +import hep.dataforge.vision.react.objectTree import hep.dataforge.vision.solid.Point3D import hep.dataforge.vision.solid.SolidGroup import hep.dataforge.vision.solid.box diff --git a/ui/bootstrap/src/main/kotlin/hep/dataforge/vision/bootstrap/MetaViewerComponent.kt b/ui/bootstrap/src/main/kotlin/hep/dataforge/vision/bootstrap/MetaViewerComponent.kt index a8bd0f26..d4809611 100644 --- a/ui/bootstrap/src/main/kotlin/hep/dataforge/vision/bootstrap/MetaViewerComponent.kt +++ b/ui/bootstrap/src/main/kotlin/hep/dataforge/vision/bootstrap/MetaViewerComponent.kt @@ -7,11 +7,8 @@ import hep.dataforge.names.NameToken import kotlinx.html.classes import kotlinx.html.js.onClickFunction import org.w3c.dom.events.Event -import react.RBuilder -import react.RComponent -import react.RProps +import react.* import react.dom.* -import react.setState interface MetaViewerProps : RProps { var name: NameToken @@ -19,6 +16,12 @@ interface MetaViewerProps : RProps { var descriptor: NodeDescriptor? } + +interface TreeState : RState { + var expanded: Boolean +} + +@Deprecated("To be replaced by react functional component") class MetaViewerComponent : RComponent() { override fun TreeState.init() { diff --git a/ui/bootstrap/src/main/kotlin/hep/dataforge/vision/bootstrap/bootstrap.kt b/ui/bootstrap/src/main/kotlin/hep/dataforge/vision/bootstrap/bootstrap.kt index a0561bd1..d624be23 100644 --- a/ui/bootstrap/src/main/kotlin/hep/dataforge/vision/bootstrap/bootstrap.kt +++ b/ui/bootstrap/src/main/kotlin/hep/dataforge/vision/bootstrap/bootstrap.kt @@ -2,12 +2,16 @@ package hep.dataforge.vision.bootstrap import hep.dataforge.names.Name import hep.dataforge.names.NameToken +import hep.dataforge.vision.Vision +import hep.dataforge.vision.react.ObjectTree import kotlinx.html.* import kotlinx.html.js.div import kotlinx.html.js.onClickFunction +import org.w3c.dom.Element import org.w3c.dom.HTMLElement import react.RBuilder import react.ReactElement +import react.child import react.dom.* inline fun TagConsumer.card(title: String, crossinline block: TagConsumer.() -> Unit) { @@ -205,4 +209,20 @@ inline fun RBuilder.gridRow( block: RDOMBuilder
.() -> Unit ): ReactElement { return div(joinStyles(classes, "row"), block) +} + +fun Element.renderObjectTree( + vision: Vision, + clickCallback: (Name) -> Unit = {} +) = render(this) { + card("Object tree") { + child(ObjectTree) { + attrs { + this.name = Name.EMPTY + this.obj = vision + this.selected = null + this.clickCallback = clickCallback + } + } + } } \ No newline at end of file diff --git a/ui/react/src/main/kotlin/hep/dataforge/vision/react/configEditor.kt b/ui/react/src/main/kotlin/hep/dataforge/vision/react/ConfigEditor.kt similarity index 82% rename from ui/react/src/main/kotlin/hep/dataforge/vision/react/configEditor.kt rename to ui/react/src/main/kotlin/hep/dataforge/vision/react/ConfigEditor.kt index 7f99d087..9331f581 100644 --- a/ui/react/src/main/kotlin/hep/dataforge/vision/react/configEditor.kt +++ b/ui/react/src/main/kotlin/hep/dataforge/vision/react/ConfigEditor.kt @@ -6,13 +6,10 @@ import hep.dataforge.names.Name import hep.dataforge.names.NameToken import hep.dataforge.names.plus import hep.dataforge.values.Value -import kotlinx.css.* -import kotlinx.css.properties.TextDecoration import kotlinx.html.js.onClickFunction import org.w3c.dom.Element import org.w3c.dom.events.Event import react.* -import react.dom.div import react.dom.render import styled.* @@ -86,7 +83,10 @@ private fun RFBuilder.configEditorItem(props: ConfigEditorItemProps) { when (actualItem) { is MetaItem.NodeItem -> { - div { + styledDiv { + css { + +TreeStyles.treeLeaf + } styledSpan { css { +TreeStyles.treeCaret @@ -145,15 +145,14 @@ private fun RFBuilder.configEditorItem(props: ConfigEditorItemProps) { styledDiv { css { +TreeStyles.treeLeaf - justifyContent = JustifyContent.flexEnd +// justifyContent = JustifyContent.flexEnd } styledDiv { css { - flexGrow = 1.0 + +TreeStyles.treeLabel } styledSpan { css { - +TreeStyles.treeLabel if (item == null) { +TreeStyles.treeLabelInactive } @@ -162,6 +161,9 @@ private fun RFBuilder.configEditorItem(props: ConfigEditorItemProps) { } } styledDiv { + css { + +TreeStyles.resizeableInput + } valueChooser( props.name, actualItem, @@ -169,37 +171,20 @@ private fun RFBuilder.configEditorItem(props: ConfigEditorItemProps) { valueChanged ) } - styledDiv { + styledButton { css { - flexShrink = 1.0 + +TreeStyles.removeButton } - styledButton { - css { - backgroundColor = Color.white - borderStyle = BorderStyle.solid - borderRadius = 2.px - padding(1.px, 5.px) - marginLeft = 4.px - textAlign = TextAlign.center - textDecoration = TextDecoration.none - display = Display.inlineBlock - cursor = Cursor.pointer - disabled { - cursor = Cursor.auto - borderStyle = BorderStyle.dashed - color = Color.lightGray - } - } - +"\u00D7" - attrs { - if (item == null) { - disabled = true - } else { - onClickFunction = removeClick - } + +"\u00D7" + attrs { + if (item == null) { + disabled = true + } else { + onClickFunction = removeClick } } } + } } } diff --git a/ui/bootstrap/src/main/kotlin/hep/dataforge/vision/bootstrap/ObjectTree.kt b/ui/react/src/main/kotlin/hep/dataforge/vision/react/ObjectTree.kt similarity index 69% rename from ui/bootstrap/src/main/kotlin/hep/dataforge/vision/bootstrap/ObjectTree.kt rename to ui/react/src/main/kotlin/hep/dataforge/vision/react/ObjectTree.kt index d2ed503f..3b2112fb 100644 --- a/ui/bootstrap/src/main/kotlin/hep/dataforge/vision/bootstrap/ObjectTree.kt +++ b/ui/react/src/main/kotlin/hep/dataforge/vision/react/ObjectTree.kt @@ -1,4 +1,4 @@ -package hep.dataforge.vision.bootstrap +package hep.dataforge.vision.react import hep.dataforge.names.Name import hep.dataforge.names.plus @@ -6,14 +6,10 @@ import hep.dataforge.names.startsWith import hep.dataforge.vision.Vision import hep.dataforge.vision.VisionGroup import hep.dataforge.vision.isEmpty -import hep.dataforge.vision.react.RFBuilder -import hep.dataforge.vision.react.component -import kotlinx.html.classes import kotlinx.html.js.onClickFunction -import org.w3c.dom.Element import org.w3c.dom.events.Event import react.* -import react.dom.* +import styled.* interface ObjectTreeProps : RProps { var name: Name @@ -22,24 +18,25 @@ interface ObjectTreeProps : RProps { var clickCallback: (Name) -> Unit } -interface TreeState : RState { - var expanded: Boolean -} - private fun RFBuilder.objectTree(props: ObjectTreeProps): Unit { - var expanded: Boolean by useState{ props.selected?.startsWith(props.name) ?: false } + var expanded: Boolean by useState { props.selected?.startsWith(props.name) ?: false } val onClick: (Event) -> Unit = { expanded = !expanded } fun RBuilder.treeLabel(text: String) { - button(classes = "btn btn-link align-middle tree-label p-0") { + styledButton { + css { + //classes = mutableListOf("btn", "btn-link", "align-middle", "text-truncate", "p-0") + +TreeStyles.treeLabel + +TreeStyles.linkButton + if (props.name == props.selected) { + +TreeStyles.treeLabelSelected + } + } +text attrs { - if (props.name == props.selected) { - classes += "tree-label-selected" - } onClickFunction = { props.clickCallback(props.name) } } } @@ -50,13 +47,19 @@ private fun RFBuilder.objectTree(props: ObjectTreeProps): Unit { //display as node if any child is visible if (obj is VisionGroup) { - div("d-block text-truncate") { + styledDiv { + css { + +TreeStyles.treeLeaf + } if (obj.children.any { !it.key.body.startsWith("@") }) { - span("tree-caret") { - attrs { + styledSpan { + css { + +TreeStyles.treeCaret if (expanded) { - classes += "tree-caret-down" + +TreeStyles.treeCaredDown } + } + attrs { onClickFunction = onClick } } @@ -64,12 +67,18 @@ private fun RFBuilder.objectTree(props: ObjectTreeProps): Unit { treeLabel(token) } if (expanded) { - ul("tree") { + styledUl { + css { + +TreeStyles.tree + } obj.children.entries .filter { !it.key.toString().startsWith("@") } // ignore statics and other hidden children - .sortedBy { (it.value as? VisionGroup)?.isEmpty ?: true } + .sortedBy { (it.value as? VisionGroup)?.isEmpty ?: true } // ignore empty groups .forEach { (childToken, child) -> - li("tree-item") { + styledLi { + css { + +TreeStyles.treeItem + } child(ObjectTree) { attrs { this.name = props.name + childToken @@ -83,8 +92,10 @@ private fun RFBuilder.objectTree(props: ObjectTreeProps): Unit { } } } else { - div("d-block text-truncate") { - span("tree-leaf") {} + styledDiv { + css { + +TreeStyles.treeLeaf + } treeLabel(token) } } @@ -94,22 +105,6 @@ val ObjectTree: FunctionalComponent = component { props -> objectTree(props) } -fun Element.renderObjectTree( - vision: Vision, - clickCallback: (Name) -> Unit = {} -) = render(this) { - card("Object tree") { - child(ObjectTree) { - attrs { - this.name = Name.EMPTY - this.obj = vision - this.selected = null - this.clickCallback = clickCallback - } - } - } -} - fun RBuilder.objectTree( vision: Vision, selected: Name? = null, diff --git a/ui/react/src/main/kotlin/hep/dataforge/vision/react/TreeStyles.kt b/ui/react/src/main/kotlin/hep/dataforge/vision/react/TreeStyles.kt index d28a6ede..ead7d577 100644 --- a/ui/react/src/main/kotlin/hep/dataforge/vision/react/TreeStyles.kt +++ b/ui/react/src/main/kotlin/hep/dataforge/vision/react/TreeStyles.kt @@ -1,8 +1,7 @@ package hep.dataforge.vision.react import kotlinx.css.* -import kotlinx.css.properties.deg -import kotlinx.css.properties.rotate +import kotlinx.css.properties.* import styled.StyleSheet object TreeStyles : StyleSheet("treeStyles", true) { @@ -30,22 +29,6 @@ object TreeStyles : StyleSheet("treeStyles", true) { } } - val treeItem by css { - alignItems = Align.center - paddingLeft = 10.px - borderLeftStyle = BorderStyle.dashed - borderLeftWidth = 1.px - borderLeftColor = Color.lightGray - } - - val treeLeaf by css { - display = Display.flex - flexDirection = FlexDirection.row - userSelect = UserSelect.none - alignItems = Align.center - } - - /** * Rotate the caret/arrow icon when clicked on (using JavaScript) */ @@ -59,8 +42,27 @@ object TreeStyles : StyleSheet("treeStyles", true) { } } + val treeItem by css { + alignItems = Align.center + paddingLeft = 10.px + borderLeftStyle = BorderStyle.dashed + borderLeftWidth = 1.px + borderLeftColor = Color.lightGray + borderBottomStyle = BorderStyle.dashed + borderBottomWidth = 1.px + borderBottomColor = Color.lightGray + } + + val treeLeaf by css { + display = Display.flex + flexDirection = FlexDirection.row + flexWrap = FlexWrap.nowrap + //alignItems = Align.center + } + val treeLabel by css { overflow = Overflow.hidden + flex(flexGrow = 1.0, flexShrink = 1.0) } val treeLabelInactive by css { @@ -71,4 +73,49 @@ object TreeStyles : StyleSheet("treeStyles", true) { backgroundColor = Color.lightBlue } + val linkButton by css { + backgroundColor = Color.white + border = "none" + padding(left = 4.pt, right = 4.pt, top = 0.pt, bottom = 0.pt) + textAlign = TextAlign.left + fontFamily = "arial,sans-serif" + color = Color("#069") + cursor = Cursor.pointer + hover { + textDecoration(TextDecorationLine.underline) + } + } + + val removeButton by css { + backgroundColor = Color.white + borderStyle = BorderStyle.solid + borderRadius = 2.px + padding(1.px, 5.px) + marginLeft = 4.px + textAlign = TextAlign.center + textDecoration = TextDecoration.none + display = Display.inlineBlock + flexShrink = 1.0 + cursor = Cursor.pointer + disabled { + cursor = Cursor.auto + borderStyle = BorderStyle.dashed + color = Color.lightGray + } + } + + val resizeableInput by css { + overflow = Overflow.hidden + maxWidth = 120.pt + flex(flexGrow = 2.0, flexShrink = 2.0, flexBasis = 60.pt) + input { + textAlign = TextAlign.right + width = 100.pct + } + select{ + textAlign = TextAlign.right + width = 100.pct + } + } + } \ No newline at end of file diff --git a/ui/react/src/main/kotlin/hep/dataforge/vision/react/valueChooser.kt b/ui/react/src/main/kotlin/hep/dataforge/vision/react/valueChooser.kt index e7562131..cf51b5aa 100644 --- a/ui/react/src/main/kotlin/hep/dataforge/vision/react/valueChooser.kt +++ b/ui/react/src/main/kotlin/hep/dataforge/vision/react/valueChooser.kt @@ -6,8 +6,6 @@ import hep.dataforge.names.Name import hep.dataforge.values.* import hep.dataforge.vision.Colors import hep.dataforge.vision.widgetType -import kotlinx.css.Align -import kotlinx.css.alignSelf import kotlinx.html.InputType import kotlinx.html.js.onChangeFunction import kotlinx.html.js.onKeyDownFunction @@ -17,11 +15,9 @@ import org.w3c.dom.HTMLSelectElement import org.w3c.dom.events.Event import react.* import react.dom.defaultValue -import react.dom.input import react.dom.option -import react.dom.select -import styled.css -import styled.styledDiv +import styled.styledInput +import styled.styledSelect interface ValueChooserProps : RProps { var item: MetaItem<*>? @@ -75,7 +71,7 @@ class ValueChooserComponent(props: ValueChooserProps) : RComponent stringInput() + descriptor?.widgetType == "color" -> styledInput(type = InputType.color) { + ref = element + attrs { + this.defaultValue = props.item?.value?.let { value -> + if (value.type == ValueType.NUMBER) Colors.rgbToString(value.int) + else value.string + } ?: "#000000" + onChangeFunction = commit + } } - val descriptor = props.descriptor - val type = descriptor?.type?.firstOrNull() - when { - state.rawInput == true -> stringInput() - descriptor?.widgetType == "color" -> input(type = InputType.color) { + type == ValueType.BOOLEAN -> { + styledInput(type = InputType.checkBox) { ref = element attrs { - this.defaultValue = props.item?.value?.let { value -> - if (value.type == ValueType.NUMBER) Colors.rgbToString(value.int) - else value.string - } ?: "#000000" + defaultChecked = props.item?.boolean ?: false onChangeFunction = commit } } - type == ValueType.BOOLEAN -> { - input(type = InputType.checkBox) { - ref = element - attrs { - defaultChecked = props.item?.boolean ?: false - onChangeFunction = commit - } - } - } - type == ValueType.NUMBER -> input(type = InputType.number) { - ref = element - attrs { - descriptor.attributes["step"].string?.let { - step = it - } - descriptor.attributes["min"].string?.let { - min = it - } - descriptor.attributes["max"].string?.let { - max = it - } - defaultValue = props.item?.string ?: "" - onKeyDownFunction = keyDown - } - } - descriptor?.allowedValues?.isNotEmpty() ?: false -> select { - descriptor!!.allowedValues.forEach { - option { - +it.string - } - } - ref = element - attrs { - this.value = props.item?.string ?: "" - multiple = false - onChangeFunction = commit - } - } - else -> stringInput() } + type == ValueType.NUMBER -> styledInput(type = InputType.number) { + ref = element + attrs { + descriptor.attributes["step"].string?.let { + step = it + } + descriptor.attributes["min"].string?.let { + min = it + } + descriptor.attributes["max"].string?.let { + max = it + } + defaultValue = props.item?.string ?: "" + onKeyDownFunction = keyDown + } + } + descriptor?.allowedValues?.isNotEmpty() ?: false -> styledSelect { + descriptor!!.allowedValues.forEach { + option { + +it.string + } + } + ref = element + attrs { + this.value = props.item?.string ?: "" + multiple = false + onChangeFunction = commit + } + } + else -> stringInput() } } - } internal fun RBuilder.valueChooser( From 48705e66705168b1d5d66508e24a0a55a2693a31 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Mon, 10 Aug 2020 22:28:05 +0300 Subject: [PATCH 002/151] Style viewer and styles resolution fix for proxies. --- .../vision/gdml/demo/GDMLAppComponent.kt | 39 +++-- .../mipt/npm/muon/monitor/server/MMServer.kt | 2 + gradle/wrapper/gradle-wrapper.jar | Bin 58694 -> 58910 bytes gradle/wrapper/gradle-wrapper.properties | 2 +- gradlew | 2 + gradlew.bat | 1 + playground/src/jsMain/kotlin/PlayGroundApp.kt | 5 +- .../vision/bootstrap/MetaViewerComponent.kt | 87 ---------- .../vision/bootstrap/propertyEditor.kt | 49 ------ .../vision/bootstrap/visionPropertyEditor.kt | 45 +++++ .../dataforge/vision/react/ConfigEditor.kt | 16 +- .../hep/dataforge/vision/react/MetaViewer.kt | 157 ++++++++++++++++++ .../hep/dataforge/vision/react/styles.kt | 9 - .../kotlin/hep/dataforge/vision/StyleSheet.kt | 10 -- .../kotlin/hep/dataforge/vision/Vision.kt | 16 +- .../hep/dataforge/vision/VisionManager.kt | 2 +- .../editor/VisualObjectEditorFragment.kt | 1 - .../hep/dataforge/vision/solid/Proxy.kt | 18 +- .../dataforge/vision/solid/serialization.kt | 2 +- .../hep/dataforge/vision/solid/ConvexTest.kt | 6 +- .../dataforge/vision/solid/PropertyTest.kt | 1 - 21 files changed, 265 insertions(+), 205 deletions(-) delete mode 100644 ui/bootstrap/src/main/kotlin/hep/dataforge/vision/bootstrap/MetaViewerComponent.kt delete mode 100644 ui/bootstrap/src/main/kotlin/hep/dataforge/vision/bootstrap/propertyEditor.kt create mode 100644 ui/bootstrap/src/main/kotlin/hep/dataforge/vision/bootstrap/visionPropertyEditor.kt create mode 100644 ui/react/src/main/kotlin/hep/dataforge/vision/react/MetaViewer.kt delete mode 100644 ui/react/src/main/kotlin/hep/dataforge/vision/react/styles.kt diff --git a/demo/gdml/src/jsMain/kotlin/hep/dataforge/vision/gdml/demo/GDMLAppComponent.kt b/demo/gdml/src/jsMain/kotlin/hep/dataforge/vision/gdml/demo/GDMLAppComponent.kt index c189b6b8..f6d7d016 100644 --- a/demo/gdml/src/jsMain/kotlin/hep/dataforge/vision/gdml/demo/GDMLAppComponent.kt +++ b/demo/gdml/src/jsMain/kotlin/hep/dataforge/vision/gdml/demo/GDMLAppComponent.kt @@ -7,7 +7,10 @@ import hep.dataforge.vision.Vision import hep.dataforge.vision.VisionGroup import hep.dataforge.vision.bootstrap.* import hep.dataforge.vision.gdml.toVision -import hep.dataforge.vision.react.* +import hep.dataforge.vision.react.component +import hep.dataforge.vision.react.flexColumn +import hep.dataforge.vision.react.objectTree +import hep.dataforge.vision.react.state import hep.dataforge.vision.solid.Solid import hep.dataforge.vision.solid.SolidGroup import hep.dataforge.vision.solid.specifications.Camera @@ -78,7 +81,7 @@ val GDMLApp = component { props -> classes.add("p-1") overflow = Overflow.auto } - gridColumn(3, maxSize= GridMaxSize.XL, classes = "order-2 order-xl-1") { + gridColumn(3, maxSize = GridMaxSize.XL, classes = "order-2 order-xl-1") { card("Load data") { fileDrop("(drag file here)") { files -> val file = files?.get(0) @@ -102,7 +105,7 @@ val GDMLApp = component { props -> } } - gridColumn(6, maxSize= GridMaxSize.XL, classes = "order-1 order-xl-2") { + gridColumn(6, maxSize = GridMaxSize.XL, classes = "order-1 order-xl-2") { //canvas (visual as? Solid)?.let { visual3D -> child(ThreeCanvasComponent::class) { @@ -118,7 +121,7 @@ val GDMLApp = component { props -> } } } - gridColumn(3, maxSize= GridMaxSize.XL, classes = "order-3") { + gridColumn(3, maxSize = GridMaxSize.XL, classes = "order-3") { container { //settings canvas?.let { @@ -127,25 +130,25 @@ val GDMLApp = component { props -> } } } - container { - namecrumbs(selected, "World") { selected = it } - } container { //properties - card("Properties") { - selected.let { selected -> - val selectedObject: Vision? = when { - selected == null -> null - selected.isEmpty() -> visual - else -> (visual as? VisionGroup)?.get(selected) - } - if (selectedObject != null) { - configEditor(selectedObject, default = selectedObject.getAllProperties(), key = selected) - } + namecrumbs(selected, "World") { selected = it } + selected.let { selected -> + val selectedObject: Vision? = when { + selected == null -> null + selected.isEmpty() -> visual + else -> (visual as? VisionGroup)?.get(selected) + } + if (selectedObject != null) { + visionPropertyEditor( + selectedObject, + default = selectedObject.getAllProperties(), + key = selected + ) } } } } } } -} \ No newline at end of file +} diff --git a/demo/muon-monitor/src/jvmMain/kotlin/ru/mipt/npm/muon/monitor/server/MMServer.kt b/demo/muon-monitor/src/jvmMain/kotlin/ru/mipt/npm/muon/monitor/server/MMServer.kt index 2052ffe8..d1e637b4 100644 --- a/demo/muon-monitor/src/jvmMain/kotlin/ru/mipt/npm/muon/monitor/server/MMServer.kt +++ b/demo/muon-monitor/src/jvmMain/kotlin/ru/mipt/npm/muon/monitor/server/MMServer.kt @@ -1,6 +1,7 @@ package ru.mipt.npm.muon.monitor.server +import hep.dataforge.meta.DFExperimental import hep.dataforge.vision.solid.SolidManager import io.ktor.application.Application import io.ktor.application.call @@ -28,6 +29,7 @@ import java.net.URI private val generator = Cos2TrackGenerator(JDKRandomGenerator(223)) +@OptIn(DFExperimental::class) fun Application.module() { val currentDir = File(".").absoluteFile environment.log.info("Current directory: $currentDir") diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 490fda8577df6c95960ba7077c43220e5bb2c0d9..62d4c053550b91381bbd28b1afc82d634bf73a8a 100644 GIT binary patch delta 6447 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 F{|nTN-B$nr diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index a4b44297..bb8b2fc2 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.3-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-6.5.1-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index 2fe81a7d..fbd7c515 100644 --- a/gradlew +++ b/gradlew @@ -82,6 +82,7 @@ esac CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + # Determine the Java command to use to start the JVM. if [ -n "$JAVA_HOME" ] ; then if [ -x "$JAVA_HOME/jre/sh/java" ] ; then @@ -129,6 +130,7 @@ fi if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then APP_HOME=`cygpath --path --mixed "$APP_HOME"` CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + JAVACMD=`cygpath --unix "$JAVACMD"` # We build the pattern for arguments to be converted via cygpath diff --git a/gradlew.bat b/gradlew.bat index 62bd9b9c..5093609d 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -84,6 +84,7 @@ set CMD_LINE_ARGS=%* set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + @rem Execute Gradle "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% diff --git a/playground/src/jsMain/kotlin/PlayGroundApp.kt b/playground/src/jsMain/kotlin/PlayGroundApp.kt index 3b8a04a4..ea95c926 100644 --- a/playground/src/jsMain/kotlin/PlayGroundApp.kt +++ b/playground/src/jsMain/kotlin/PlayGroundApp.kt @@ -1,8 +1,7 @@ import hep.dataforge.context.Global import hep.dataforge.js.Application import hep.dataforge.js.startApplication -import hep.dataforge.names.Name -import hep.dataforge.vision.bootstrap.visualPropertyEditor +import hep.dataforge.vision.bootstrap.visionPropertyEditor import hep.dataforge.vision.react.objectTree import hep.dataforge.vision.solid.Point3D import hep.dataforge.vision.solid.SolidGroup @@ -41,7 +40,7 @@ private class PlayGroundApp : Application { threeCanvas(obj) } div("col-3") { - visualPropertyEditor(Name.EMPTY, obj) + visionPropertyEditor(obj) } } } diff --git a/ui/bootstrap/src/main/kotlin/hep/dataforge/vision/bootstrap/MetaViewerComponent.kt b/ui/bootstrap/src/main/kotlin/hep/dataforge/vision/bootstrap/MetaViewerComponent.kt deleted file mode 100644 index d4809611..00000000 --- a/ui/bootstrap/src/main/kotlin/hep/dataforge/vision/bootstrap/MetaViewerComponent.kt +++ /dev/null @@ -1,87 +0,0 @@ -package hep.dataforge.vision.bootstrap - -import hep.dataforge.meta.Meta -import hep.dataforge.meta.MetaItem -import hep.dataforge.meta.descriptors.NodeDescriptor -import hep.dataforge.names.NameToken -import kotlinx.html.classes -import kotlinx.html.js.onClickFunction -import org.w3c.dom.events.Event -import react.* -import react.dom.* - -interface MetaViewerProps : RProps { - var name: NameToken - var meta: Meta - var descriptor: NodeDescriptor? -} - - -interface TreeState : RState { - var expanded: Boolean -} - -@Deprecated("To be replaced by react functional component") -class MetaViewerComponent : RComponent() { - - override fun TreeState.init() { - expanded = false - } - - private val onClick: (Event) -> Unit = { - setState { - expanded = !expanded - } - } - - override fun RBuilder.render() { - div("d-inline-block text-truncate") { - if (props.meta.items.isNotEmpty()) { - span("tree-caret") { - attrs { - if (state.expanded) { - classes += "tree-caret-down" - } - onClickFunction = onClick - } - } - } - label("tree-label") { - +props.name.toString() - } - ul("tree") { - props.meta.items.forEach { (token, item) -> - //val descriptor = props. - li { - when (item) { - is MetaItem.NodeItem -> { - child(MetaViewerComponent::class) { - attrs { - name = token - meta = item.node - descriptor = props.descriptor?.nodes?.get(token.body) - } - } - } - is MetaItem.ValueItem -> { - div("row") { - div("col") { - label("tree-label") { - +token.toString() - } - } - div("col") { - label { - +item.value.toString() - } - } - } - } - } - } - } - } - } - } - -} \ No newline at end of file diff --git a/ui/bootstrap/src/main/kotlin/hep/dataforge/vision/bootstrap/propertyEditor.kt b/ui/bootstrap/src/main/kotlin/hep/dataforge/vision/bootstrap/propertyEditor.kt deleted file mode 100644 index d51375ee..00000000 --- a/ui/bootstrap/src/main/kotlin/hep/dataforge/vision/bootstrap/propertyEditor.kt +++ /dev/null @@ -1,49 +0,0 @@ -package hep.dataforge.vision.bootstrap - -import hep.dataforge.meta.Meta -import hep.dataforge.meta.descriptors.NodeDescriptor -import hep.dataforge.names.Name -import hep.dataforge.names.isEmpty -import hep.dataforge.vision.Vision -import hep.dataforge.vision.react.configEditor -import org.w3c.dom.Element -import react.RBuilder -import react.dom.li -import react.dom.nav -import react.dom.ol -import react.dom.render -import kotlin.collections.set - -fun RBuilder.visualPropertyEditor( - path: Name, - item: Vision, - descriptor: NodeDescriptor? = item.descriptor, - default: Meta? = null -) { - card("Properties") { - if (!path.isEmpty()) { - nav { - attrs { - attributes["aria-label"] = "breadcrumb" - } - ol("breadcrumb") { - path.tokens.forEach { token -> - li("breadcrumb-item") { - +token.toString() - } - } - } - } - } - configEditor(item, descriptor, default) - } -} - -fun Element.visualPropertyEditor( - path: Name, - item: Vision, - descriptor: NodeDescriptor? = item.descriptor, - default: Meta? = null -) = render(this) { - this.visualPropertyEditor(path, item, descriptor, default) -} \ No newline at end of file diff --git a/ui/bootstrap/src/main/kotlin/hep/dataforge/vision/bootstrap/visionPropertyEditor.kt b/ui/bootstrap/src/main/kotlin/hep/dataforge/vision/bootstrap/visionPropertyEditor.kt new file mode 100644 index 00000000..0c46e386 --- /dev/null +++ b/ui/bootstrap/src/main/kotlin/hep/dataforge/vision/bootstrap/visionPropertyEditor.kt @@ -0,0 +1,45 @@ +package hep.dataforge.vision.bootstrap + +import hep.dataforge.meta.Meta +import hep.dataforge.meta.descriptors.NodeDescriptor +import hep.dataforge.vision.Vision +import hep.dataforge.vision.react.configEditor +import hep.dataforge.vision.react.metaViewer +import hep.dataforge.vision.resolveStyle +import org.w3c.dom.Element +import react.RBuilder +import react.dom.render + +fun RBuilder.visionPropertyEditor( + item: Vision, + descriptor: NodeDescriptor? = item.descriptor, + default: Meta? = null, + key: Any? = null +) { + card("Properties") { + configEditor(item, descriptor, default, key) + } + val styles = item.styles + if(styles.isNotEmpty()) { + card("Styles") { + accordion("styles") { + styles.forEach { styleName -> + val style = item.resolveStyle(styleName) + if (style != null) { + entry(styleName) { + metaViewer(style) + } + } + } + } + } + } +} + +fun Element.visionPropertyEditor( + item: Vision, + descriptor: NodeDescriptor? = item.descriptor, + default: Meta? = null +) = render(this) { + visionPropertyEditor(item, descriptor, default) +} \ No newline at end of file diff --git a/ui/react/src/main/kotlin/hep/dataforge/vision/react/ConfigEditor.kt b/ui/react/src/main/kotlin/hep/dataforge/vision/react/ConfigEditor.kt index 9331f581..712d3b60 100644 --- a/ui/react/src/main/kotlin/hep/dataforge/vision/react/ConfigEditor.kt +++ b/ui/react/src/main/kotlin/hep/dataforge/vision/react/ConfigEditor.kt @@ -113,7 +113,7 @@ private fun RFBuilder.configEditorItem(props: ConfigEditorItemProps) { css { +TreeStyles.tree } - val keys = buildSet { + val keys = buildSet { (descriptorItem as? NodeDescriptor)?.items?.keys?.forEach { add(NameToken(it)) } @@ -121,7 +121,7 @@ private fun RFBuilder.configEditorItem(props: ConfigEditorItemProps) { defaultItem?.node?.items?.keys?.let { addAll(it) } } - keys.forEach { token -> + keys.filter { !it.body.startsWith("@") }.forEach { token -> styledLi { css { +TreeStyles.treeItem @@ -145,7 +145,6 @@ private fun RFBuilder.configEditorItem(props: ConfigEditorItemProps) { styledDiv { css { +TreeStyles.treeLeaf -// justifyContent = JustifyContent.flexEnd } styledDiv { css { @@ -238,13 +237,4 @@ fun RBuilder.configEditor( descriptor: NodeDescriptor? = obj.descriptor, default: Meta? = null, key: Any? = null -) { - child(ConfigEditor) { - attrs { - this.key = key?.toString() ?: "" - this.root = obj.config - this.descriptor = descriptor - this.default = default - } - } -} +) = configEditor(obj.config,descriptor, default, key) diff --git a/ui/react/src/main/kotlin/hep/dataforge/vision/react/MetaViewer.kt b/ui/react/src/main/kotlin/hep/dataforge/vision/react/MetaViewer.kt new file mode 100644 index 00000000..e5a628b4 --- /dev/null +++ b/ui/react/src/main/kotlin/hep/dataforge/vision/react/MetaViewer.kt @@ -0,0 +1,157 @@ +package hep.dataforge.vision.react + +import hep.dataforge.meta.Meta +import hep.dataforge.meta.MetaItem +import hep.dataforge.meta.descriptors.ItemDescriptor +import hep.dataforge.meta.descriptors.NodeDescriptor +import hep.dataforge.meta.descriptors.defaultItem +import hep.dataforge.meta.descriptors.get +import hep.dataforge.meta.get +import hep.dataforge.names.Name +import hep.dataforge.names.NameToken +import hep.dataforge.names.plus +import kotlinx.html.js.onClickFunction +import org.w3c.dom.events.Event +import react.* +import react.dom.a +import styled.* + +interface MetaViewerProps : RProps { + /** + * Root meta + */ + var root: Meta + + /** + * Full path to the displayed node in [root]. Could be empty + */ + var name: Name + + /** + * Root descriptor + */ + var descriptor: NodeDescriptor? +} + +private val MetaViewerItem: FunctionalComponent = component { props -> + metaViewerItem(props) +} + +private fun RFBuilder.metaViewerItem(props: MetaViewerProps) { + var expanded: Boolean by state { true } + val item = props.root[props.name] + val descriptorItem: ItemDescriptor? = props.descriptor?.get(props.name) + val actualItem = item ?: descriptorItem?.defaultItem() + + val token = props.name.last()?.toString() ?: "Meta" + + val expanderClick: (Event) -> Unit = { + expanded = !expanded + } + + when (actualItem) { + is MetaItem.NodeItem -> { + styledDiv { + css { + +TreeStyles.treeLeaf + } + styledSpan { + css { + +TreeStyles.treeCaret + if (expanded) { + +TreeStyles.treeCaredDown + } + } + attrs { + onClickFunction = expanderClick + } + } + styledSpan { + css { + +TreeStyles.treeLabel + if (item == null) { + +TreeStyles.treeLabelInactive + } + } + +token + } + } + if (expanded) { + styledUl { + css { + +TreeStyles.tree + } + val keys = buildSet { + (descriptorItem as? NodeDescriptor)?.items?.keys?.forEach { + add(NameToken(it)) + } + actualItem.node.items.keys.let { addAll(it) } + } + + keys.filter { !it.body.startsWith("@") }.forEach { token -> + styledLi { + css { + +TreeStyles.treeItem + } + child(MetaViewerItem) { + attrs { + this.key = props.name.toString() + this.root = props.root + this.name = props.name + token + this.descriptor = props.descriptor + } + } + //configEditor(props.root, props.name + token, props.descriptor, props.default) + } + } + } + } + } + is MetaItem.ValueItem -> { + styledDiv { + css { + +TreeStyles.treeLeaf + } + styledDiv { + css { + +TreeStyles.treeLabel + } + styledSpan { + css { + if (item == null) { + +TreeStyles.treeLabelInactive + } + } + +token + } + } + styledDiv { + a { + +actualItem.value.toString() + } + } + } + } + } +} + +val MetaViewer = component { props -> + child(MetaViewerItem) { + attrs { + this.key = "" + this.root = props.root + this.name = Name.EMPTY + this.descriptor = props.descriptor + } + } +} + +fun RBuilder.metaViewer(meta: Meta, descriptor: NodeDescriptor? = null, key: Any? = null) { + child(MetaViewer) { + attrs { + this.key = key?.toString() ?: "" + this.root = meta + this.descriptor = descriptor + } + } +} diff --git a/ui/react/src/main/kotlin/hep/dataforge/vision/react/styles.kt b/ui/react/src/main/kotlin/hep/dataforge/vision/react/styles.kt deleted file mode 100644 index 5a3a7576..00000000 --- a/ui/react/src/main/kotlin/hep/dataforge/vision/react/styles.kt +++ /dev/null @@ -1,9 +0,0 @@ -package hep.dataforge.vision.react - -import styled.StyleSheet - - -class MainStyle: StyleSheet("main", true){ - - -} \ No newline at end of file diff --git a/visionforge-core/src/commonMain/kotlin/hep/dataforge/vision/StyleSheet.kt b/visionforge-core/src/commonMain/kotlin/hep/dataforge/vision/StyleSheet.kt index 4dfb28d1..1ff736c9 100644 --- a/visionforge-core/src/commonMain/kotlin/hep/dataforge/vision/StyleSheet.kt +++ b/visionforge-core/src/commonMain/kotlin/hep/dataforge/vision/StyleSheet.kt @@ -5,7 +5,6 @@ package hep.dataforge.vision import hep.dataforge.meta.* import hep.dataforge.names.Name import hep.dataforge.names.asName -import hep.dataforge.values.asValue import kotlinx.serialization.* import kotlinx.serialization.builtins.MapSerializer import kotlinx.serialization.builtins.serializer @@ -90,15 +89,6 @@ class StyleSheet private constructor(private val styleMap: MutableMap - get() = properties?.get(Vision.STYLE_KEY).stringList - set(value) { - setItem(Vision.STYLE_KEY,value.map { it.asValue() }.asValue()) - } - /** * Add style name to the list of styles to be resolved later. The style with given name does not necessary exist at the moment. */ diff --git a/visionforge-core/src/commonMain/kotlin/hep/dataforge/vision/Vision.kt b/visionforge-core/src/commonMain/kotlin/hep/dataforge/vision/Vision.kt index 8af6989b..1b8bcabd 100644 --- a/visionforge-core/src/commonMain/kotlin/hep/dataforge/vision/Vision.kt +++ b/visionforge-core/src/commonMain/kotlin/hep/dataforge/vision/Vision.kt @@ -5,6 +5,7 @@ import hep.dataforge.names.Name import hep.dataforge.names.asName import hep.dataforge.names.toName import hep.dataforge.provider.Type +import hep.dataforge.values.asValue import hep.dataforge.vision.Vision.Companion.TYPE import kotlinx.serialization.PolymorphicSerializer import kotlinx.serialization.Transient @@ -56,13 +57,22 @@ interface Vision : Configurable { */ fun removeChangeListener(owner: Any?) + /** + * List of names of styles applied to this object. Order matters. Not inherited. + */ + var styles: List + get() = properties[STYLE_KEY].stringList + set(value) { + setItem(STYLE_KEY,value.map { it.asValue() }.asValue()) + } + companion object { - const val TYPE = "visual" + const val TYPE = "vision" val STYLE_KEY = "@style".asName() - private val VISUAL_OBJECT_SERIALIZER = PolymorphicSerializer(Vision::class) + private val VISION_SERIALIZER = PolymorphicSerializer(Vision::class) - fun serializer() = VISUAL_OBJECT_SERIALIZER + fun serializer() = VISION_SERIALIZER } } diff --git a/visionforge-core/src/commonMain/kotlin/hep/dataforge/vision/VisionManager.kt b/visionforge-core/src/commonMain/kotlin/hep/dataforge/vision/VisionManager.kt index 4bebd56a..6bf7291c 100644 --- a/visionforge-core/src/commonMain/kotlin/hep/dataforge/vision/VisionManager.kt +++ b/visionforge-core/src/commonMain/kotlin/hep/dataforge/vision/VisionManager.kt @@ -84,7 +84,7 @@ class VisionManager(meta: Meta) : AbstractPlugin(meta) { } fun buildVision(meta: Meta): Vision { - val type = meta["type"].string ?: SimpleVisionGroup.serializer().descriptor.serialName + val type = meta["type"].string ?: Vision.serializer().descriptor.serialName val form = forms.values.find { it.name.toString() == type } ?: error("Could not resolve a form for type $type") return form.buildVision(meta, visionSerialModule) } diff --git a/visionforge-core/src/jvmMain/kotlin/hep/dataforge/vision/editor/VisualObjectEditorFragment.kt b/visionforge-core/src/jvmMain/kotlin/hep/dataforge/vision/editor/VisualObjectEditorFragment.kt index 846fad14..7da6885d 100644 --- a/visionforge-core/src/jvmMain/kotlin/hep/dataforge/vision/editor/VisualObjectEditorFragment.kt +++ b/visionforge-core/src/jvmMain/kotlin/hep/dataforge/vision/editor/VisualObjectEditorFragment.kt @@ -6,7 +6,6 @@ import hep.dataforge.meta.descriptors.NodeDescriptor import hep.dataforge.meta.update import hep.dataforge.vision.Vision import hep.dataforge.vision.resolveStyle -import hep.dataforge.vision.styles import javafx.beans.binding.Binding import javafx.beans.property.SimpleObjectProperty import javafx.scene.Node diff --git a/visionforge-solid/src/commonMain/kotlin/hep/dataforge/vision/solid/Proxy.kt b/visionforge-solid/src/commonMain/kotlin/hep/dataforge/vision/solid/Proxy.kt index 463434cc..53d65b0a 100644 --- a/visionforge-solid/src/commonMain/kotlin/hep/dataforge/vision/solid/Proxy.kt +++ b/visionforge-solid/src/commonMain/kotlin/hep/dataforge/vision/solid/Proxy.kt @@ -2,12 +2,10 @@ package hep.dataforge.vision.solid -import hep.dataforge.meta.Config -import hep.dataforge.meta.Laminate -import hep.dataforge.meta.MetaItem +import hep.dataforge.meta.* import hep.dataforge.meta.descriptors.NodeDescriptor -import hep.dataforge.meta.get import hep.dataforge.names.* +import hep.dataforge.values.asValue import hep.dataforge.vision.* import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable @@ -89,6 +87,12 @@ class Proxy private constructor( //override fun findAllStyles(): Laminate = Laminate((styles + prototype.styles).mapNotNull { findStyle(it) }) + override var styles: List + get() = properties[Vision.STYLE_KEY].stringList + prototype.styles + set(value) { + setItem(Vision.STYLE_KEY, value.map { it.asValue() }.asValue()) + } + override val descriptor: NodeDescriptor? get() = prototype.descriptor @@ -147,6 +151,12 @@ class Proxy private constructor( Laminate(properties, allStyles, prototype.getAllProperties(), parent?.getAllProperties()) + override var styles: List + get() = properties[Vision.STYLE_KEY].stringList + prototype.styles + set(value) { + setItem(Vision.STYLE_KEY, value.map { it.asValue() }.asValue()) + } + override val descriptor: NodeDescriptor? get() = prototype.descriptor } diff --git a/visionforge-solid/src/commonMain/kotlin/hep/dataforge/vision/solid/serialization.kt b/visionforge-solid/src/commonMain/kotlin/hep/dataforge/vision/solid/serialization.kt index ba672093..0b0a4d0b 100644 --- a/visionforge-solid/src/commonMain/kotlin/hep/dataforge/vision/solid/serialization.kt +++ b/visionforge-solid/src/commonMain/kotlin/hep/dataforge/vision/solid/serialization.kt @@ -123,7 +123,7 @@ internal object PrototypesSerializer : KSerializer { fun Vision.stringify(): String = SolidManager.jsonForSolids.stringify(Vision.serializer(), this) @OptIn(DFExperimental::class) -fun Vision.Companion.parseJson(str: String) = SolidManager.jsonForSolids.parse(Vision.serializer(), str).also { +fun Vision.Companion.parseJson(str: String) = SolidManager.jsonForSolids.parse(serializer(), str).also { if(it is VisionGroup){ it.attachChildren() } diff --git a/visionforge-solid/src/commonTest/kotlin/hep/dataforge/vision/solid/ConvexTest.kt b/visionforge-solid/src/commonTest/kotlin/hep/dataforge/vision/solid/ConvexTest.kt index 8dc87500..0afb5a7c 100644 --- a/visionforge-solid/src/commonTest/kotlin/hep/dataforge/vision/solid/ConvexTest.kt +++ b/visionforge-solid/src/commonTest/kotlin/hep/dataforge/vision/solid/ConvexTest.kt @@ -1,13 +1,11 @@ package hep.dataforge.vision.solid -import hep.dataforge.meta.MetaItem -import hep.dataforge.meta.getIndexed -import hep.dataforge.meta.node -import hep.dataforge.meta.toMetaItem +import hep.dataforge.meta.* import kotlin.test.Test import kotlin.test.assertEquals class ConvexTest { + @OptIn(DFExperimental::class) @Suppress("UNUSED_VARIABLE") @Test fun testConvexBuilder() { diff --git a/visionforge-solid/src/commonTest/kotlin/hep/dataforge/vision/solid/PropertyTest.kt b/visionforge-solid/src/commonTest/kotlin/hep/dataforge/vision/solid/PropertyTest.kt index efa9e1a0..48c7ec9d 100644 --- a/visionforge-solid/src/commonTest/kotlin/hep/dataforge/vision/solid/PropertyTest.kt +++ b/visionforge-solid/src/commonTest/kotlin/hep/dataforge/vision/solid/PropertyTest.kt @@ -3,7 +3,6 @@ package hep.dataforge.vision.solid import hep.dataforge.meta.int import hep.dataforge.meta.set import hep.dataforge.names.asName -import hep.dataforge.vision.styles import hep.dataforge.vision.useStyle import kotlin.test.Test import kotlin.test.assertEquals From a5eba1789b35e6124e198be5a71fef6085744042 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Wed, 26 Aug 2020 10:16:55 +0300 Subject: [PATCH 003/151] GDML optimization --- demo/gdml/build.gradle.kts | 3 +- .../vision/gdml/demo/GDMLAppComponent.kt | 42 ++- .../demo/{GDMLDemoApp.kt => GdmlJsDemoApp.kt} | 31 +- .../demo/{GDMLDemoApp.kt => GdmlFxDemoApp.kt} | 11 +- .../vision/solid/demo/VariableBox.kt | 2 +- gradle/wrapper/gradle-wrapper.jar | Bin 58910 -> 59203 bytes gradle/wrapper/gradle-wrapper.properties | 2 +- gradlew | 2 +- gradlew.bat | 21 +- .../dataforge/vision/bootstrap/bootstrap.kt | 33 +- .../hep/dataforge/vision/VisionGroup.kt | 5 +- .../vision/visitor/StatisticsVisitor.kt | 35 +++ .../dataforge/vision/visitor/VisionVisitor.kt | 55 ++++ .../dataforge/vision/visitor/countDistinct.kt | 16 + .../dataforge/vision/gdml/GDMLTransformer.kt | 287 +++++++++++++++++- .../dataforge/vision/gdml/GdmlOptimizer.kt | 89 ++++++ .../hep/dataforge/vision/gdml/GdmlVision.kt | 268 ---------------- .../hep/dataforge/vision/gdml/gdmlJs.kt | 8 + .../gdml/{visualGDMLJvm.kt => gdmlJVM.kt} | 4 +- .../dataforge/vision/gdml/TestConvertor.kt | 5 +- .../dataforge/vision/gdml/bmanStatistics.kt | 34 +++ .../hep/dataforge/vision/solid/Proxy.kt | 6 +- .../hep/dataforge/vision/solid/Solid.kt | 4 +- .../vision/solid/three/MeshThreeFactory.kt | 43 +-- .../vision/solid/three/ThreeFactory.kt | 2 +- .../vision/solid/three/ThreeLabelFactory.kt | 2 +- .../vision/solid/three/ThreeLineFactory.kt | 2 +- .../vision/solid/three/ThreeMaterials.kt | 34 ++- .../vision/solid/three/ThreePlugin.kt | 2 +- .../vision/solid/three/ThreeProxyFactory.kt | 24 +- .../info/laht/threekt/objects/LineSegments.kt | 3 + 31 files changed, 671 insertions(+), 404 deletions(-) rename demo/gdml/src/jsMain/kotlin/hep/dataforge/vision/gdml/demo/{GDMLDemoApp.kt => GdmlJsDemoApp.kt} (52%) rename demo/gdml/src/jvmMain/kotlin/hep/dataforge/vision/gdml/demo/{GDMLDemoApp.kt => GdmlFxDemoApp.kt} (86%) create mode 100644 visionforge-core/src/commonMain/kotlin/hep/dataforge/vision/visitor/StatisticsVisitor.kt create mode 100644 visionforge-core/src/commonMain/kotlin/hep/dataforge/vision/visitor/VisionVisitor.kt create mode 100644 visionforge-core/src/jvmMain/kotlin/hep/dataforge/vision/visitor/countDistinct.kt create mode 100644 visionforge-gdml/src/commonMain/kotlin/hep/dataforge/vision/gdml/GdmlOptimizer.kt delete mode 100644 visionforge-gdml/src/commonMain/kotlin/hep/dataforge/vision/gdml/GdmlVision.kt create mode 100644 visionforge-gdml/src/jsMain/kotlin/hep/dataforge/vision/gdml/gdmlJs.kt rename visionforge-gdml/src/jvmMain/kotlin/hep/dataforge/vision/gdml/{visualGDMLJvm.kt => gdmlJVM.kt} (85%) create mode 100644 visionforge-gdml/src/jvmTest/kotlin/hep/dataforge/vision/gdml/bmanStatistics.kt diff --git a/demo/gdml/build.gradle.kts b/demo/gdml/build.gradle.kts index c16fce83..8d5342c3 100644 --- a/demo/gdml/build.gradle.kts +++ b/demo/gdml/build.gradle.kts @@ -1,6 +1,5 @@ import scientifik.DependencyConfiguration import scientifik.FXModule -import scientifik.useFx plugins { id("scientifik.mpp") @@ -37,7 +36,7 @@ kotlin { } application { - mainClassName = "hep.dataforge.vision.gdml.demo.GDMLDemoAppKt" + mainClassName = "hep.dataforge.vision.gdml.demo.GdmlFxDemoAppKt" } val convertGdmlToJson by tasks.creating(JavaExec::class) { diff --git a/demo/gdml/src/jsMain/kotlin/hep/dataforge/vision/gdml/demo/GDMLAppComponent.kt b/demo/gdml/src/jsMain/kotlin/hep/dataforge/vision/gdml/demo/GDMLAppComponent.kt index f6d7d016..ae1dce60 100644 --- a/demo/gdml/src/jsMain/kotlin/hep/dataforge/vision/gdml/demo/GDMLAppComponent.kt +++ b/demo/gdml/src/jsMain/kotlin/hep/dataforge/vision/gdml/demo/GDMLAppComponent.kt @@ -1,6 +1,7 @@ package hep.dataforge.vision.gdml.demo import hep.dataforge.context.Context +import hep.dataforge.meta.set import hep.dataforge.names.Name import hep.dataforge.names.isEmpty import hep.dataforge.vision.Vision @@ -8,7 +9,6 @@ import hep.dataforge.vision.VisionGroup import hep.dataforge.vision.bootstrap.* import hep.dataforge.vision.gdml.toVision import hep.dataforge.vision.react.component -import hep.dataforge.vision.react.flexColumn import hep.dataforge.vision.react.objectTree import hep.dataforge.vision.react.state import hep.dataforge.vision.solid.Solid @@ -29,7 +29,6 @@ import react.dom.h1 import scientifik.gdml.GDML import scientifik.gdml.parse import styled.css -import styled.styledDiv import kotlin.browser.window import kotlin.math.PI @@ -50,14 +49,14 @@ private val canvasConfig = Canvas3DOptions { val GDMLApp = component { props -> var selected by state { props.selected } var canvas: ThreeCanvas? by state { null } - var visual: Vision? by state { props.rootObject } + var vision: Vision? by state { props.rootObject } val select: (Name?) -> Unit = { selected = it } fun loadData(name: String, data: String) { - visual = when { + val parsedVision = when { name.endsWith(".gdml") || name.endsWith(".xml") -> { val gdml = GDML.parse(data) gdml.toVision(gdmlConfiguration) @@ -68,20 +67,26 @@ val GDMLApp = component { props -> error("File extension is not recognized: $name") } } + parsedVision.config["edges.enabled"] = false + + vision = parsedVision } - flexColumn { + gridColumn { css { flex(1.0, 1.0, FlexBasis.auto) } h1 { +"GDML/JSON loader demo" } - styledDiv { + gridRow { css { - classes.add("row") - classes.add("p-1") + +"p-1" overflow = Overflow.auto } - gridColumn(3, maxSize = GridMaxSize.XL, classes = "order-2 order-xl-1") { + gridColumn(3, maxSize = GridMaxSize.XL) { + css { + +"order-2" + +"order-xl-1" + } card("Load data") { fileDrop("(drag file here)") { files -> val file = files?.get(0) @@ -99,15 +104,19 @@ val GDMLApp = component { props -> } //tree card("Object tree") { - visual?.let { + vision?.let { objectTree(it, selected, select) } } } - gridColumn(6, maxSize = GridMaxSize.XL, classes = "order-1 order-xl-2") { + gridColumn(6, maxSize = GridMaxSize.XL) { + css { + +"order-1" + +"order-xl-2" + } //canvas - (visual as? Solid)?.let { visual3D -> + (vision as? Solid)?.let { visual3D -> child(ThreeCanvasComponent::class) { attrs { this.context = props.context @@ -121,7 +130,10 @@ val GDMLApp = component { props -> } } } - gridColumn(3, maxSize = GridMaxSize.XL, classes = "order-3") { + gridColumn(3, maxSize = GridMaxSize.XL) { + css { + +"order-3" + } container { //settings canvas?.let { @@ -136,8 +148,8 @@ val GDMLApp = component { props -> selected.let { selected -> val selectedObject: Vision? = when { selected == null -> null - selected.isEmpty() -> visual - else -> (visual as? VisionGroup)?.get(selected) + selected.isEmpty() -> vision + else -> (vision as? VisionGroup)?.get(selected) } if (selectedObject != null) { visionPropertyEditor( diff --git a/demo/gdml/src/jsMain/kotlin/hep/dataforge/vision/gdml/demo/GDMLDemoApp.kt b/demo/gdml/src/jsMain/kotlin/hep/dataforge/vision/gdml/demo/GdmlJsDemoApp.kt similarity index 52% rename from demo/gdml/src/jsMain/kotlin/hep/dataforge/vision/gdml/demo/GDMLDemoApp.kt rename to demo/gdml/src/jsMain/kotlin/hep/dataforge/vision/gdml/demo/GdmlJsDemoApp.kt index 56b9fecd..40d35a09 100644 --- a/demo/gdml/src/jsMain/kotlin/hep/dataforge/vision/gdml/demo/GDMLDemoApp.kt +++ b/demo/gdml/src/jsMain/kotlin/hep/dataforge/vision/gdml/demo/GdmlJsDemoApp.kt @@ -16,23 +16,9 @@ import kotlin.browser.document val gdmlConfiguration: GDMLTransformer.() -> Unit = { lUnit = LUnit.CM - volumeAction = { volume -> - when { - volume.name.startsWith("ecal01lay") -> GDMLTransformer.Action.REJECT - volume.name.startsWith("UPBL") -> GDMLTransformer.Action.REJECT - volume.name.startsWith("USCL") -> GDMLTransformer.Action.REJECT - volume.name.startsWith("VPBL") -> GDMLTransformer.Action.REJECT - volume.name.startsWith("VSCL") -> GDMLTransformer.Action.REJECT - else -> GDMLTransformer.Action.CACHE - } - } - solidConfiguration = { parent, solid -> - if ( - solid.name.startsWith("Yoke") - || solid.name.startsWith("Pole") - || parent.physVolumes.isNotEmpty() - ) { + solidConfiguration = { parent, _ -> + if (parent.physVolumes.isNotEmpty()) { useStyle("opaque") { MATERIAL_OPACITY_KEY put 0.3 } @@ -64,19 +50,6 @@ private class GDMLDemoApp : Application { } } } -// (document.getElementById("file_load_button") as? HTMLInputElement)?.apply { -// addEventListener("change", { -// (it.target as HTMLInputElement).files?.asList()?.first()?.let { file -> -// FileReader().apply { -// onload = { -// val string = result as String -// action(file.name, string) -// } -// readAsText(file) -// } -// } -// }, false) -// } } } diff --git a/demo/gdml/src/jvmMain/kotlin/hep/dataforge/vision/gdml/demo/GDMLDemoApp.kt b/demo/gdml/src/jvmMain/kotlin/hep/dataforge/vision/gdml/demo/GdmlFxDemoApp.kt similarity index 86% rename from demo/gdml/src/jvmMain/kotlin/hep/dataforge/vision/gdml/demo/GDMLDemoApp.kt rename to demo/gdml/src/jvmMain/kotlin/hep/dataforge/vision/gdml/demo/GdmlFxDemoApp.kt index 35b00615..c69682b8 100644 --- a/demo/gdml/src/jvmMain/kotlin/hep/dataforge/vision/gdml/demo/GDMLDemoApp.kt +++ b/demo/gdml/src/jvmMain/kotlin/hep/dataforge/vision/gdml/demo/GdmlFxDemoApp.kt @@ -36,12 +36,11 @@ class GDMLView : View() { buttonbar { button("Load GDML/json") { action { - runAsync { - val file = chooseFile("Select a GDML/json file", filters = fileNameFilter).firstOrNull() - ?: return@runAsync null - SolidManager.readFile(file) - } ui { - if (it != null) { + val file = chooseFile("Select a GDML/json file", filters = fileNameFilter).firstOrNull() + if(file!= null) { + runAsync { + SolidManager.readFile(file) + } ui { canvas.render(it) } } diff --git a/demo/spatial-showcase/src/jsMain/kotlin/hep/dataforge/vision/solid/demo/VariableBox.kt b/demo/spatial-showcase/src/jsMain/kotlin/hep/dataforge/vision/solid/demo/VariableBox.kt index 3664d4a5..abe6097b 100644 --- a/demo/spatial-showcase/src/jsMain/kotlin/hep/dataforge/vision/solid/demo/VariableBox.kt +++ b/demo/spatial-showcase/src/jsMain/kotlin/hep/dataforge/vision/solid/demo/VariableBox.kt @@ -71,7 +71,7 @@ private object VariableBoxThreeFactory : ThreeFactory { //JS sometimes tries to pass Geometry as BufferGeometry @Suppress("USELESS_IS_CHECK") if (geometry !is BufferGeometry) error("BufferGeometry expected") - val mesh = Mesh(geometry, getMaterial(obj)).apply { + val mesh = Mesh(geometry, getMaterial(obj,true)).apply { applyEdges(obj) applyWireFrame(obj) diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 62d4c053550b91381bbd28b1afc82d634bf73a8a..e708b1c023ec8b20f512888fe07c5bd3ff77bb8f 100644 GIT binary patch delta 6656 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 Yte!%o?r4GTrVtxD61Ym!|5fq-1K$0e!T1w z1SC8j)_dObefzK9b=~*c&wBRW>;B{VGKiBofK!FMN5oJBE0V;;!kWUz!jc1W?5KdY zyZ3mCBHprpchz-9{ASiJJh&&h1|4rdw6wxD2+9= z#6#}Uq8&^1F3wgvGFoNDo?bIeEQXpcuAR0-+w$JWoK-@yUal1M&~W_O)r+Rx;{@hWH5n^oQWR36GMYBDDZyPK4L@WVjRrF+XlSzi4X4!_!U%Uujl6LHQ#|l(sUU%{ zefYd8jnVYP91K}Qn-OmmSLYFK1h~_}RPS~>+Xdz%dpvpJ{ll!IKX=JN99qowqslbO zV3DmqPZ}6>KB!9>jEObpi$u5oGPfO3O5!o3N2Mn`ozpje<}1I1H)m2rJDcB7AwXc6 z6j)tnPiql7#)r+b+p9?MVahp&=qJ^$oG+a^C*);FoJ!+V*^W+|2Olx5{*&$bXth)U zejc7mU6cBp?^Rj|dd{GL-0eHRTBi6_yJ&GLP5kIncv^z{?=0AVy^5{S8_n=rtua!J zFGY=A(yV^ZhB}1J_y(F`3QTu+zkHlw;1GiFeP&pw0N1k%NShHlO(4W+(!wy5phcg4 zA-|}(lE_1@@e6y`veg;v7m;q%(PFG&K3#}eRhJioXUU0jg_8{kn$;KVwf;zpL2X_( zC*_R#5*PaBaY73(x*oZ}oE#HPLJQRQ7brNK=v!lsu==lSG1(&q>F)`adBT~d*lMS| z%!%7(p~<7kWNmpZ5-N31*e=8`kih|g5lVrI%2wnLF-2D+G4k6@FrYsJ_80AJ}KMRi>) z-kIeHp{maorNWkF81v0FKgB==_6blyaF$5GaW)B!i4v*jNk6r)vU6?G$0pV8(Y+UK z5lgRVt%;N_gWp)^osv=h+^07UY6+$4^#t=M3>0i0`{`aEkFLL#a)93uXhYO+aKTtu zckg2T9S&GKNtZmdAS^8PzvDva-%-K&g9eqPXQ4$dM^inr@6Zl z{!Cq&C_+V;g*{>!0cZP}?ogDb$#ZS=n@NHE{>k@84lOkl&$Bt2NF)W%GClViJq14_ zQIfa^q+0aq){}CO8j%g%R9|;G0uJuND*HO$2i&U_uW_a5xJ33~(Vy?;%6_(2_Cuq1 zLhThN@xH7-BaNtkKTn^taQHrs$<<)euc6z(dhps>SM;^Wx=7;O&IfNVJq3wk4<1VS z-`*7W4DR_i^W4=dRh>AXi~J$K>`UqP>CKVVH&+T(ODhRJZO7DScU$F7D)di-%^8?O z6)Ux`zdrVOe1GNkPo0FgrrxSu1AGQkJe@pqu}8LkBDm+V!N_1l}`tjLW8${rgDLv3m@E*#zappt-Mm zSC<$o+6UO~w0C=(0$&*y**@nKe_Q{|eAuD!(0YL0_a{z%+sdfSyP={Nyd$re6Rzbp zvsgTY7~VflX0^Vf7qqomYZ_$ryrFVV2$sFyzw2r%Q8*uYDA+)iQdfKms_5(>!s#!( z!P5S(N0i9CKQKaqg(U%Gk#V3*?)lO6dLv`8KB~F<-%VhbtL8Rl>mEz+PN=qx&t*|= zQHV=qG)YKlPk4iCyWIUGjC?kpeA>hIBK*A?B0)rB=RqAal#D%1C9yVQwBcz${#Jb5 zR{TRmMrOrJsLc&6x9qDo@FJ^=do_Y?3oU0G^nV5_EU&+DS+VA7Tp{^TAF>yZbyM3c zf*1CqHY9T|aL_lyY7c)i!_MtGPA!sdy3|mrsKVj1mi&>dms@-ozSa}OZ?2I*tAndg z@S7er$t^d^-;!wLQbG60nWd@1pQVD7tw-G_B#OscoYyremiZ_hj8*sXqQdchuD^!R zpXGuSj5psk+jR>3rWu3^`17>j&*^9^rWbszP=Mf@5KIEj%b=z98v=Ymp%$FYt>%Ld zm8})EDbNOJu9n)gwhz_RS``#Ag)fr)3<*?(!9O~mTQWeh;8c;0@o=iBLQNqx3d_2#W7S9#FXzr6VXfs>4 z;QXw}-STvK9_-7H=uqgal2{GkbjVLN+=D5ddd)4^WvX;(NYA*X*(JxTdiUzqVJopd zQg#~psX4o<)cF>r=rxP`(Xsf<+HG-pf&7aFPL8z|-&B*P?Vmsu5d>Nlg^2$WRY!S@#`g2{81;(1w#o5HsvN}5pFZi});>|VK^kL{Zkx~wgn ztlZp;HW`H8(GdRfIwc~?#N6}o#h158ohI*GIsK%56I_9sf2k_K@4vD!l{(dX9E7PJ;w>$|Y;-VBJSO4@){07bo-89^LZ9g<<%;dOl zyIq{s8`8Ltp*GDwu(l_Z$6sA2nam$BM$Q~6TpZg)w2TtW?G5whV(lRwaf$6EU86is zBP9Rs&vS_~sk?Nn_b}^HkM8LiO@>J}=g(T4hLmvH@5Jj#2aHa~K)lD9VB0k>$V2BP zgh;(=y9Op(KQ=H5vj+%qs>?s4tYN~-Q|fyQePA)s?HrF~;l!+@t8VMzqUpqMLudFT z)=o~s!MM4XkgbetIsODwtQ=FF$IcIp&!pjh6Q6{tL+l*7GQ%8Wsg(tC#qU3oW$~n) zL=>XIxI}Hi7HS0F_mmi+(c%1HDuKiWm>|6Xa}nW7ei55ggru9)xjBvC#JcEIN*#cp zv*ACvr=HTC?dX9NNo9Yhulu_gX5Z~}QQ2&QZ&C77{(>Y3_ z6j5Z1Uc5FtPEpS_31HsgmSLHZijGb_p$WlRJ1p^_1!ZLP8kr6OtCEK7Qh267o$H>e zf<4cNGQRk{g5h$XfvTFQ@`qm@iju83-~}ebAYpZryARHVR$AEt3229U{y@Fp4 z-8FBBtGG&(hTyUdx5ZOfiz`c=<0F%+w|Fl=rWk{K7>70k04SN?RU(^mrKSeKDqA!K^Hsv8C?#ioj4@WUL zC*?{hTai6q0%_oBTqDHygp_Kl;({sAScYQIwMDM1U>{x0ww zve?_}E;DG?+|zsUrsph5X_G7l#Y~vqkq3@NNDabbw7|`eJBmn`Qrlr%?`va=mm$Mc{+FBbQbogAZ6{MuzT|P%QZZotd21eb1hfj|;GYAX&>bx#D5EB+=XMj2XJkpnyMUykaVo) zj3ZLqEl1&)Rturc8m@+uUuD^vaNaSxGwP4dq0-OSb~62lPv8E_K4usLvG{Qg zdR%z8dd2H!{JaT|X_bfm{##*W$YM;_J8Y8&Z)*ImOAf4+| zEyi)qK%Ld1bHuqD+}-WiCnjszDeC-%8g+8JRpG1bOc!xUGB?@?6f~FTrI%U#5R~YF z%t5(S2Q>?0`(XNHa8xKdTEZ~Z4SJOheit#ldfdg63}#W6j8kO;SjQD`vftxS+#x1B zYu|5szEvkyz|}|B3x|DNlyi$;+n+cW$Hu+?)=X1!sa%{H-^;oBO9XACZJ}wkQ!sTa zQ#J3h|HX{{&WwIG3h7d6aWktuJaO)ie6&=KJBoX@w(rBWfin`*a6OmCC5M0HzL(gv zY<*e4hmW>SWVhxk-`UGOAbD%Hk+uu<^7zJ_ytVXamfqCd0$g+W08>?QAB}Cv{b}eM z@X}ILg+uT%>-6`A25p@uhS3%;u>ccSq}8|H_^o&`nBT5S0y z;2H0I^(4MO*S+(4l$gULc4KSeKvidto5Nl0P|%9CqQ*ikY!w_GUlo}sb9HYB=L^oFpJ zfTQskXW!LFVnUo4(OHPDaZSf3zB|3{RGu1>ueE$(+dr?tT zp!SGlqDU8vu{5xLWSvj+j$arHglg54#Lx&TvuO3LIIU>hF9Uoj&=-b*Q?uYr`#V?xz?2 zhirZrv^eA{k%{hFh%9LYVXEYWd5#PuUd1QqaqB*J!CMXEM>fEB$@#1>mtB`Bfil}t zhhTIObqh5HRvT+4q_Do$Q*Jika?qV=Np-DtPkU z(KoXyWLfPwr@UY1)hBAvR3nCBZgd|CevTG?H~HqDF}dzy%2sd2`f{^CBbTk*^K~RO zN~O0+2EjAJlywF%SjgYz810l&G5AqzI<=Ber{912^PpSPRJl3dm8W@dKHL}7_@k3)Y!SXYkyxQy>Q4I2o zr`ev7fLF$1t96h|sH<-#*YzGD-b^3$_!#wsh(Yw;)b@udLz9mm`mFYh z1Zz24KIQJ(*_-E0(3&1InqG;U?wF)GYd>DFo(em`#|UaaYmkA9;GTX7b?0@C@QkTVpGD#mf$dQoRNV=n{^Zi_W*ps;3?^$s`0;ER7;==~OmQ~9 zS5P=FjxE5%|;xq6h4@!_h?@|aK&FYI2IT(OHXv2%1 zWEo-v!L7x^YT(xLVHlpJttcwaF@1Y;-S*q3CRa!g7xdzl|Jan>2#dI0`LKl!T1GMk zRKe4|bQO&ET}Z^Aiym*HII>cSxIzl|F~JEUGxz;+DB=8fxXhnBI4R12q6ews$lA`Jfi}r@A@-)6TOAUMNYFYJ zZ-Zd?lxFTyjN3mXnL!%#>Z%$0gJ4*9g;e;@zSmQ{eGGDaRRNM3s@6!;hYuVc=c+3B z=qzNNS~n^EsJU4aOGE|mdy={C^lPKEfPL-IJAsTpQsDgZ@~s+eHZYmp9yb=YW_4r?lqQaYZQ`nau){W`LY#P)>i zq^wHEuOYs#FlPZeMuT@Etb@~A6feCebq`miJE3w+gAL%bVF_s*5e*@)?xmKSo%I3? zLELHVdWia$}~s6 zr!^LfxSSB4Td&9iTXrzQpl5ZDo#SdmNr;23QsPHQ!x!UT9xtb!Ycz^JF8x)%cFOXK z^EXw%dRz_VD}7?RU^4{)1+xFO=z!EI8IUa3U*rag=1BpHX$Xi<__kSbS{y_xa*MJv z_`thq0Z^sPzjAk48ssDQj}!$N8Q$XC84(bU$t_Bm69Jf+C!h_}ep zwzpQj9sRA94<{x3{~z&ix-DwX;RAzka)4-#6ZHJqKh|SVuO|>Yrv+m30+!|sK<-|E z=)5E->#y<_1V|T1f%Af!ZYqXg}`O zI$qKOWdnclF`%_Z`WGOe{`A`l-#a?s=Q1a#@BOWmExH2;Wl`OB!B-%lq3nO{4=WO& z#k_x|N&(qzm*6S{G*|GCegF2N2ulC+(58z2DG~yUs}i8zvRf&$CJCaexJ6Xu!`qz( z)*v8*kAE#D0KCo*s{8^Rbg=`*E2MzeIt0|x55%n-gO&yX#$l=3W7-_~&(G8j1E(XB hw}tl`5K!1C(72%nnjQrp<7@!WCh47rWB+@R{{wClNUHz< diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index bb8b2fc2..6c9a2247 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.5.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-6.6-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index fbd7c515..4f906e0c 100644 --- a/gradlew +++ b/gradlew @@ -130,7 +130,7 @@ fi if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then APP_HOME=`cygpath --path --mixed "$APP_HOME"` CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` - + JAVACMD=`cygpath --unix "$JAVACMD"` # We build the pattern for arguments to be converted via cygpath diff --git a/gradlew.bat b/gradlew.bat index 5093609d..107acd32 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -40,7 +40,7 @@ if defined JAVA_HOME goto findJavaFromJavaHome set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto init +if "%ERRORLEVEL%" == "0" goto execute echo. echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. @@ -54,7 +54,7 @@ goto fail set JAVA_HOME=%JAVA_HOME:"=% set JAVA_EXE=%JAVA_HOME%/bin/java.exe -if exist "%JAVA_EXE%" goto init +if exist "%JAVA_EXE%" goto execute echo. echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% @@ -64,21 +64,6 @@ echo location of your Java installation. goto fail -:init -@rem Get command-line arguments, handling Windows variants - -if not "%OS%" == "Windows_NT" goto win9xME_args - -:win9xME_args -@rem Slurp the command line arguments. -set CMD_LINE_ARGS= -set _SKIP=2 - -:win9xME_args_slurp -if "x%~1" == "x" goto execute - -set CMD_LINE_ARGS=%* - :execute @rem Setup the command line @@ -86,7 +71,7 @@ set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar @rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* :end @rem End local scope for the variables with windows NT shell diff --git a/ui/bootstrap/src/main/kotlin/hep/dataforge/vision/bootstrap/bootstrap.kt b/ui/bootstrap/src/main/kotlin/hep/dataforge/vision/bootstrap/bootstrap.kt index d624be23..f41c7ecc 100644 --- a/ui/bootstrap/src/main/kotlin/hep/dataforge/vision/bootstrap/bootstrap.kt +++ b/ui/bootstrap/src/main/kotlin/hep/dataforge/vision/bootstrap/bootstrap.kt @@ -13,6 +13,9 @@ import react.RBuilder import react.ReactElement import react.child import react.dom.* +import styled.StyledDOMBuilder +import styled.css +import styled.styledDiv inline fun TagConsumer.card(title: String, crossinline block: TagConsumer.() -> Unit) { div("card w-100") { @@ -180,10 +183,14 @@ enum class ContainerSize(val suffix: String) { } inline fun RBuilder.container( - classes: String? = null, size: ContainerSize = ContainerSize.FLUID, - block: RDOMBuilder
.() -> Unit -): ReactElement = div(joinStyles(classes, "container${size.suffix}"), block) + block: StyledDOMBuilder
.() -> Unit +): ReactElement = styledDiv{ + css{ + classes.add("container${size.suffix}") + } + block() +} enum class GridMaxSize(val suffix: String) { @@ -196,19 +203,23 @@ enum class GridMaxSize(val suffix: String) { inline fun RBuilder.gridColumn( weight: Int? = null, - classes: String? = null, maxSize: GridMaxSize = GridMaxSize.NONE, - block: RDOMBuilder
.() -> Unit -): ReactElement { + block: StyledDOMBuilder
.() -> Unit +): ReactElement = styledDiv { val weightSuffix = weight?.let { "-$it" } ?: "" - return div(joinStyles(classes, "col${maxSize.suffix}$weightSuffix"), block) + css { + classes.add("col${maxSize.suffix}$weightSuffix") + } + block() } inline fun RBuilder.gridRow( - classes: String? = null, - block: RDOMBuilder
.() -> Unit -): ReactElement { - return div(joinStyles(classes, "row"), block) + block: StyledDOMBuilder
.() -> Unit +): ReactElement = styledDiv{ + css{ + classes.add("row") + } + block() } fun Element.renderObjectTree( diff --git a/visionforge-core/src/commonMain/kotlin/hep/dataforge/vision/VisionGroup.kt b/visionforge-core/src/commonMain/kotlin/hep/dataforge/vision/VisionGroup.kt index cae2e2b0..43b964f2 100644 --- a/visionforge-core/src/commonMain/kotlin/hep/dataforge/vision/VisionGroup.kt +++ b/visionforge-core/src/commonMain/kotlin/hep/dataforge/vision/VisionGroup.kt @@ -91,8 +91,7 @@ interface MutableVisionGroup : VisionGroup { operator fun VisionGroup.get(str: String?): Vision? = get(str?.toName() ?: Name.EMPTY) -operator fun MutableVisionGroup.set(key: String, child: Vision?) { - set(key.toName(), child) -} +operator fun MutableVisionGroup.set(token: NameToken, child: Vision?): Unit = set(token.asName(), child) +operator fun MutableVisionGroup.set(key: String, child: Vision?): Unit = set(key.toName(), child) fun MutableVisionGroup.removeAll() = children.keys.map { it.asName() }.forEach { this[it] = null } \ No newline at end of file diff --git a/visionforge-core/src/commonMain/kotlin/hep/dataforge/vision/visitor/StatisticsVisitor.kt b/visionforge-core/src/commonMain/kotlin/hep/dataforge/vision/visitor/StatisticsVisitor.kt new file mode 100644 index 00000000..21842994 --- /dev/null +++ b/visionforge-core/src/commonMain/kotlin/hep/dataforge/vision/visitor/StatisticsVisitor.kt @@ -0,0 +1,35 @@ +package hep.dataforge.vision.visitor + +import hep.dataforge.names.Name +import hep.dataforge.vision.Vision +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.Job +import kotlinx.coroutines.channels.awaitClose +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.callbackFlow +import kotlin.reflect.KClass + + +@OptIn(ExperimentalCoroutinesApi::class) +suspend fun Vision.flowStatistics(statistics: (Name, Vision) -> T): Flow = callbackFlow { + val visitor = object : VisionVisitor { + override suspend fun visit(name: Name, vision: Vision){ + send(statistics(name, vision)) + } + } + val job: Job = VisionVisitor.visitTree(visitor, this, this@flowStatistics) + job.invokeOnCompletion { + channel.close() + } + awaitClose { + job.cancel() + } +} + +data class DefaultVisionStatistics(val name: Name, val type: KClass) { + val depth get() = name.length +} + +suspend fun Vision.flowStatistics(): Flow = flowStatistics { name, vision -> + DefaultVisionStatistics(name, vision::class) +} \ No newline at end of file diff --git a/visionforge-core/src/commonMain/kotlin/hep/dataforge/vision/visitor/VisionVisitor.kt b/visionforge-core/src/commonMain/kotlin/hep/dataforge/vision/visitor/VisionVisitor.kt new file mode 100644 index 00000000..192e36a0 --- /dev/null +++ b/visionforge-core/src/commonMain/kotlin/hep/dataforge/vision/visitor/VisionVisitor.kt @@ -0,0 +1,55 @@ +package hep.dataforge.vision.visitor + +import hep.dataforge.names.Name +import hep.dataforge.names.plus +import hep.dataforge.vision.Vision +import hep.dataforge.vision.VisionGroup +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Job +import kotlinx.coroutines.launch + +interface VisionVisitor { + /** + * Visit a vision possibly mutating in in the process. Should not rearrange children. + * @param name full name of a [Vision] being visited + * @param vision the visited [Vision] + */ + suspend fun visit(name: Name, vision: Vision) + + /** + * Rearrange children of given group + */ + suspend fun visitChildren(name: Name, group: VisionGroup) { + //Do nothing by default + } + + fun skip(name: Name, vision: Vision): Boolean = false + + companion object{ + private fun CoroutineScope.visitTreeAsync( + visionVisitor: VisionVisitor, + name: Name, + vision: Vision + ): Job = launch { + if (visionVisitor.skip(name, vision)) return@launch + visionVisitor.visit(name, vision) + + if (vision is VisionGroup) { + visionVisitor.visitChildren(name, vision) + + for ((token, child) in vision.children) { + visitTreeAsync(visionVisitor, name + token, child) + } + } + } + + /** + * Recursively visit this [Vision] and all children + */ + fun visitTree(visionVisitor: VisionVisitor, scope: CoroutineScope, root: Vision): Job = + scope.visitTreeAsync(visionVisitor, Name.EMPTY, root) + + + } +} + diff --git a/visionforge-core/src/jvmMain/kotlin/hep/dataforge/vision/visitor/countDistinct.kt b/visionforge-core/src/jvmMain/kotlin/hep/dataforge/vision/visitor/countDistinct.kt new file mode 100644 index 00000000..6f9594de --- /dev/null +++ b/visionforge-core/src/jvmMain/kotlin/hep/dataforge/vision/visitor/countDistinct.kt @@ -0,0 +1,16 @@ +package hep.dataforge.vision.visitor + +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.collect +import java.util.concurrent.atomic.AtomicInteger + +suspend fun Flow.countDistinctBy(selector: (T) -> K): Map { + val counter = LinkedHashMap() + collect { + val key = selector(it) + counter.getOrPut(key) { AtomicInteger() }.incrementAndGet() + } + return counter.mapValues { it.value.toInt() } +} + +suspend fun Flow.countDistinct(): Map = countDistinctBy { it } \ No newline at end of file diff --git a/visionforge-gdml/src/commonMain/kotlin/hep/dataforge/vision/gdml/GDMLTransformer.kt b/visionforge-gdml/src/commonMain/kotlin/hep/dataforge/vision/gdml/GDMLTransformer.kt index b7019f69..82413d93 100644 --- a/visionforge-gdml/src/commonMain/kotlin/hep/dataforge/vision/gdml/GDMLTransformer.kt +++ b/visionforge-gdml/src/commonMain/kotlin/hep/dataforge/vision/gdml/GDMLTransformer.kt @@ -4,11 +4,16 @@ import hep.dataforge.meta.Meta import hep.dataforge.meta.MetaBuilder import hep.dataforge.names.Name import hep.dataforge.names.asName +import hep.dataforge.names.plus import hep.dataforge.names.toName +import hep.dataforge.vision.get +import hep.dataforge.vision.set import hep.dataforge.vision.solid.* import hep.dataforge.vision.solid.SolidMaterial.Companion.MATERIAL_COLOR_KEY import hep.dataforge.vision.useStyle import scientifik.gdml.* +import kotlin.math.cos +import kotlin.math.sin import kotlin.random.Random class GDMLTransformer(val root: GDML) { @@ -21,17 +26,16 @@ class GDMLTransformer(val root: GDML) { CACHE } - /** - * A special group for local templates - */ - val proto by lazy { SolidGroup() } - private val styleCache = HashMap() - var lUnit: LUnit = LUnit.MM var solidAction: (GDMLSolid) -> Action = { Action.CACHE } var volumeAction: (GDMLGroup) -> Action = { Action.CACHE } + /** + * A special group for local templates + */ + internal val proto by lazy { SolidGroup() } + private val styleCache = HashMap() var solidConfiguration: Solid.(parent: GDMLVolume, solid: GDMLSolid) -> Unit = { parent, _ -> lUnit = LUnit.CM @@ -86,4 +90,275 @@ class GDMLTransformer(val root: GDML) { return final } +} + +private fun Solid.withPosition( + lUnit: LUnit, + newPos: GDMLPosition? = null, + newRotation: GDMLRotation? = null, + newScale: GDMLScale? = null +): Solid = apply { + newPos?.let { + val point = Point3D(it.x(lUnit), it.y(lUnit), it.z(lUnit)) + if (position != null || point != World.ZERO) { + position = point + } + } + newRotation?.let { + val point = Point3D(it.x(), it.y(), it.z()) + if (rotation != null || point != World.ZERO) { + rotation = point + } + //this@withPosition.rotationOrder = RotationOrder.ZXY + } + newScale?.let { + val point = Point3D(it.x, it.y, it.z) + if (scale != null || point != World.ONE) { + scale = point + } + } + //TODO convert units if needed +} + +@Suppress("NOTHING_TO_INLINE") +private inline operator fun Number.times(d: Double) = toDouble() * d + +@Suppress("NOTHING_TO_INLINE") +private inline operator fun Number.times(f: Float) = toFloat() * f + +private fun SolidGroup.addSolid( + context: GDMLTransformer, + solid: GDMLSolid, + name: String = "", + block: Solid.() -> Unit = {} +): Solid { + //context.solidAdded(solid) + val lScale = solid.lscale(context.lUnit) + val aScale = solid.ascale() + return when (solid) { + is GDMLBox -> box(solid.x * lScale, solid.y * lScale, solid.z * lScale, name) + is GDMLTube -> tube( + solid.rmax * lScale, + solid.z * lScale, + solid.rmin * lScale, + solid.startphi * aScale, + solid.deltaphi * aScale, + name + ) + is GDMLCone -> cone(solid.rmax1, solid.z, solid.rmax2, name = name) { + require(solid.rmin1 == 0.0) { "Empty cones are not supported" } + require(solid.rmin2 == 0.0) { "Empty cones are not supported" } + startAngle = solid.startphi.toFloat() + angle = solid.deltaphi.toFloat() + } + is GDMLXtru -> extrude(name) { + shape { + solid.vertices.forEach { + point(it.x * lScale, it.y * lScale) + } + } + solid.sections.sortedBy { it.zOrder }.forEach { section -> + layer( + section.zPosition * lScale, + section.xOffset * lScale, + section.yOffset * lScale, + section.scalingFactor + ) + } + } + is GDMLScaledSolid -> { + //Add solid with modified scale + val innerSolid = solid.solidref.resolve(context.root) + ?: error("Solid with tag ${solid.solidref.ref} for scaled solid ${solid.name} not defined") + + addSolid(context, innerSolid, name) { + block() + scaleX *= solid.scale.x.toFloat() + scaleY *= solid.scale.y.toFloat() + scaleZ = solid.scale.z.toFloat() + } + } + is GDMLSphere -> sphere(solid.rmax * lScale, solid.deltaphi * aScale, solid.deltatheta * aScale, name) { + phiStart = solid.startphi * aScale + thetaStart = solid.starttheta * aScale + } + is GDMLOrb -> sphere(solid.r * lScale, name = name) + is GDMLPolyhedra -> extrude(name) { + //getting the radius of first + require(solid.planes.size > 1) { "The polyhedron geometry requires at least two planes" } + val baseRadius = solid.planes.first().rmax * lScale + shape { + (0..solid.numsides).forEach { + val phi = solid.deltaphi * aScale / solid.numsides * it + solid.startphi * aScale + (baseRadius * cos(phi) to baseRadius * sin(phi)) + } + } + solid.planes.forEach { plane -> + //scaling all radii relative to first layer radius + layer(plane.z * lScale, scale = plane.rmax * lScale / baseRadius) + } + } + is GDMLBoolSolid -> { + val first = solid.first.resolve(context.root) ?: error("") + val second = solid.second.resolve(context.root) ?: error("") + val type: CompositeType = when (solid) { + is GDMLUnion -> CompositeType.UNION + is GDMLSubtraction -> CompositeType.SUBTRACT + is GDMLIntersection -> CompositeType.INTERSECT + } + + return composite(type, name) { + addSolid(context, first) { + withPosition( + context.lUnit, + solid.resolveFirstPosition(context.root), + solid.resolveFirstRotation(context.root), + null + ) + } + addSolid(context, second) { + withPosition( + context.lUnit, + solid.resolvePosition(context.root), + solid.resolveRotation(context.root), + null + ) + } + } + } + else -> error("Renderer for $solid not supported yet") + }.apply(block) +} + + +private fun SolidGroup.addSolidWithCaching( + context: GDMLTransformer, + solid: GDMLSolid, + volume: GDMLVolume, + name: String = solid.name +) { + when (context.solidAction(solid)) { + GDMLTransformer.Action.ACCEPT -> { + addSolid(context, solid, name) { + context.configureSolid(this, volume, solid) + } + } + GDMLTransformer.Action.CACHE -> { + if (context.proto[solid.name] == null) { + context.proto.addSolid(context, solid, name) { + context.configureSolid(this, volume, solid) + } + } + ref(solid.name.asName(), name) + } + GDMLTransformer.Action.REJECT -> { + //ignore + } + } + +} + +private val volumesName = "volumes".asName() + +private fun SolidGroup.addPhysicalVolume( + context: GDMLTransformer, + physVolume: GDMLPhysVolume +) { + val volume: GDMLGroup = physVolume.volumeref.resolve(context.root) + ?: error("Volume with ref ${physVolume.volumeref.ref} could not be resolved") + + // a special case for single solid volume +// if (volume is GDMLVolume && volume.physVolumes.isEmpty() && volume.placement == null) { +// val solid = volume.solidref.resolve(context.root) +// ?: error("Solid with tag ${volume.solidref.ref} for volume ${volume.name} not defined") +// addSolidWithCaching(context, solid, volume, physVolume.name ?: "").apply { +// withPosition( +// context.lUnit, +// physVolume.resolvePosition(context.root), +// physVolume.resolveRotation(context.root), +// physVolume.resolveScale(context.root) +// ) +// } +// return +// } + + when (context.volumeAction(volume)) { + GDMLTransformer.Action.ACCEPT -> { + val group: SolidGroup = volume(context, volume) + this[physVolume.name ?: ""] = group.apply { + withPosition( + context.lUnit, + physVolume.resolvePosition(context.root), + physVolume.resolveRotation(context.root), + physVolume.resolveScale(context.root) + ) + } + } + GDMLTransformer.Action.CACHE -> { + val fullName = volumesName + volume.name.asName() + if (context.proto[fullName] == null) { + context.proto[fullName] = volume(context, volume) + } + + this[physVolume.name ?: ""] = Proxy(this, fullName).apply { + withPosition( + context.lUnit, + physVolume.resolvePosition(context.root), + physVolume.resolveRotation(context.root), + physVolume.resolveScale(context.root) + ) + } + } + GDMLTransformer.Action.REJECT -> { + //ignore + } + } +} + +private fun SolidGroup.addDivisionVolume( + context: GDMLTransformer, + divisionVolume: GDMLDivisionVolume +) { + val volume: GDMLGroup = divisionVolume.volumeref.resolve(context.root) + ?: error("Volume with ref ${divisionVolume.volumeref.ref} could not be resolved") + + //TODO add divisions + set(Name.EMPTY, volume(context, volume)) +} + +//private val solidsName = "solids".asName() + +private fun volume( + context: GDMLTransformer, + group: GDMLGroup +): SolidGroup = SolidGroup().apply { + if (group is GDMLVolume) { + val solid: GDMLSolid = group.solidref.resolve(context.root) + ?: error("Solid with tag ${group.solidref.ref} for volume ${group.name} not defined") + + addSolidWithCaching(context, solid, group) + + when (val vol: GDMLPlacement? = group.placement) { + is GDMLPhysVolume -> addPhysicalVolume(context, vol) + is GDMLDivisionVolume -> addDivisionVolume(context, vol) + } + } + + group.physVolumes.forEach { physVolume -> + addPhysicalVolume(context, physVolume) + } +} + +fun GDML.toVision(block: GDMLTransformer.() -> Unit = {}): SolidGroup { + val context = GDMLTransformer(this).apply(block) + return context.finalize(volume(context, world)) +} + +/** + * Append gdml node to the group + */ +fun SolidGroup.gdml(gdml: GDML, key: String = "", transformer: GDMLTransformer.() -> Unit = {}) { + val visual = gdml.toVision(transformer) + //println(Visual3DPlugin.json.stringify(VisualGroup3D.serializer(), visual)) + set(key, visual) } \ No newline at end of file diff --git a/visionforge-gdml/src/commonMain/kotlin/hep/dataforge/vision/gdml/GdmlOptimizer.kt b/visionforge-gdml/src/commonMain/kotlin/hep/dataforge/vision/gdml/GdmlOptimizer.kt new file mode 100644 index 00000000..c138fcc6 --- /dev/null +++ b/visionforge-gdml/src/commonMain/kotlin/hep/dataforge/vision/gdml/GdmlOptimizer.kt @@ -0,0 +1,89 @@ +package hep.dataforge.vision.gdml + +import hep.dataforge.meta.DFExperimental +import hep.dataforge.meta.sequence +import hep.dataforge.meta.set +import hep.dataforge.names.Name +import hep.dataforge.names.toName +import hep.dataforge.vision.* +import hep.dataforge.vision.solid.* +import hep.dataforge.vision.visitor.VisionVisitor +import kotlinx.coroutines.CompletableDeferred +import kotlinx.coroutines.Job +import kotlinx.coroutines.coroutineScope +import mu.KotlinLogging + +expect class Counter() { + fun get(): Int + fun incrementAndGet(): Int +} + +@DFExperimental +private class GdmlOptimizer() : VisionVisitor { + val logger = KotlinLogging.logger("SingleChildReducer") + + private operator fun Point3D?.plus(other: Point3D?): Point3D? = if (this == null && other == null) { + null + } else { + (this ?: Point3D(0, 0, 0)) + (other ?: Point3D(0, 0, 0)) + } + + private fun Vision.updateFrom(other: Vision): Vision { + if (this is Solid && other is Solid) { + position += other.position + rotation += other.rotation + if (this.scale != null || other.scale != null) { + scaleX = scaleX.toDouble() * other.scaleX.toDouble() + scaleY = scaleY.toDouble() * other.scaleY.toDouble() + scaleZ = scaleZ.toDouble() * other.scaleZ.toDouble() + } + other.properties?.sequence()?.forEach { (name, item) -> + if (properties?.getItem(name) == null) { + config[name] = item + } + } + } + return this + } + + private val depthCount = HashMap() + + override suspend fun visit(name: Name, vision: Vision) { + val depth = name.length + depthCount.getOrPut(depth) { Counter() }.incrementAndGet() + } + + override fun skip(name: Name, vision: Vision): Boolean = vision is Proxy.ProxyChild + + override suspend fun visitChildren(name: Name, group: VisionGroup) { + if (name == "volumes".toName()) return + if (group !is MutableVisionGroup) return + + val newChildren = group.children.entries.associate { (visionToken, vision) -> + //Reduce single child groups + if (vision is VisionGroup && vision !is Proxy && vision.children.size == 1) { + val (token, child) = vision.children.entries.first() + child.parent = null + if (token != visionToken) { + child.config["solidName"] = token.toString() + } + visionToken to child.updateFrom(vision) + } else { + visionToken to vision + } + } + if (newChildren != group.children) { + group.removeAll() + newChildren.forEach { (token, child) -> + group[token] = child + } + } + } +} + +@DFExperimental +suspend fun SolidGroup.optimizeGdml(): Job = coroutineScope { + prototypes?.let { + VisionVisitor.visitTree(GdmlOptimizer(), this, it) + } ?: CompletableDeferred(Unit) +} \ No newline at end of file diff --git a/visionforge-gdml/src/commonMain/kotlin/hep/dataforge/vision/gdml/GdmlVision.kt b/visionforge-gdml/src/commonMain/kotlin/hep/dataforge/vision/gdml/GdmlVision.kt deleted file mode 100644 index 29efa338..00000000 --- a/visionforge-gdml/src/commonMain/kotlin/hep/dataforge/vision/gdml/GdmlVision.kt +++ /dev/null @@ -1,268 +0,0 @@ -package hep.dataforge.vision.gdml - - -import hep.dataforge.names.Name -import hep.dataforge.names.asName -import hep.dataforge.names.plus -import hep.dataforge.vision.get -import hep.dataforge.vision.set -import hep.dataforge.vision.solid.* -import hep.dataforge.vision.solid.World.ONE -import hep.dataforge.vision.solid.World.ZERO -import scientifik.gdml.* -import kotlin.math.cos -import kotlin.math.sin - - -private fun Solid.withPosition( - lUnit: LUnit, - newPos: GDMLPosition? = null, - newRotation: GDMLRotation? = null, - newScale: GDMLScale? = null -): Solid = apply { - newPos?.let { - val point = Point3D(it.x(lUnit), it.y(lUnit), it.z(lUnit)) - if (position != null || point != ZERO) { - position = point - } - } - newRotation?.let { - val point = Point3D(it.x(), it.y(), it.z()) - if (rotation != null || point != ZERO) { - rotation = point - } - //this@withPosition.rotationOrder = RotationOrder.ZXY - } - newScale?.let { - val point = Point3D(it.x, it.y, it.z) - if (scale != null || point != ONE) { - scale = point - } - } - //TODO convert units if needed -} - -@Suppress("NOTHING_TO_INLINE") -private inline operator fun Number.times(d: Double) = toDouble() * d - -@Suppress("NOTHING_TO_INLINE") -private inline operator fun Number.times(f: Float) = toFloat() * f - -private fun SolidGroup.addSolid( - context: GDMLTransformer, - solid: GDMLSolid, - name: String = "", - block: Solid.() -> Unit = {} -): Solid { - //context.solidAdded(solid) - val lScale = solid.lscale(context.lUnit) - val aScale = solid.ascale() - return when (solid) { - is GDMLBox -> box(solid.x * lScale, solid.y * lScale, solid.z * lScale, name) - is GDMLTube -> tube( - solid.rmax * lScale, - solid.z * lScale, - solid.rmin * lScale, - solid.startphi * aScale, - solid.deltaphi * aScale, - name - ) - is GDMLCone -> cone(solid.rmax1, solid.z, solid.rmax2, name = name) { - require(solid.rmin1 == 0.0) { "Empty cones are not supported" } - require(solid.rmin2 == 0.0) { "Empty cones are not supported" } - startAngle = solid.startphi.toFloat() - angle = solid.deltaphi.toFloat() - } - is GDMLXtru -> extrude(name) { - shape { - solid.vertices.forEach { - point(it.x * lScale, it.y * lScale) - } - } - solid.sections.sortedBy { it.zOrder }.forEach { section -> - layer( - section.zPosition * lScale, - section.xOffset * lScale, - section.yOffset * lScale, - section.scalingFactor - ) - } - } - is GDMLScaledSolid -> { - //Add solid with modified scale - val innerSolid = solid.solidref.resolve(context.root) - ?: error("Solid with tag ${solid.solidref.ref} for scaled solid ${solid.name} not defined") - - addSolid(context, innerSolid, name) { - block() - scaleX *= solid.scale.x.toFloat() - scaleY *= solid.scale.y.toFloat() - scaleZ = solid.scale.z.toFloat() - } - } - is GDMLSphere -> sphere(solid.rmax * lScale, solid.deltaphi * aScale, solid.deltatheta * aScale, name) { - phiStart = solid.startphi * aScale - thetaStart = solid.starttheta * aScale - } - is GDMLOrb -> sphere(solid.r * lScale, name = name) - is GDMLPolyhedra -> extrude(name) { - //getting the radius of first - require(solid.planes.size > 1) { "The polyhedron geometry requires at least two planes" } - val baseRadius = solid.planes.first().rmax * lScale - shape { - (0..solid.numsides).forEach { - val phi = solid.deltaphi * aScale / solid.numsides * it + solid.startphi * aScale - (baseRadius * cos(phi) to baseRadius * sin(phi)) - } - } - solid.planes.forEach { plane -> - //scaling all radii relative to first layer radius - layer(plane.z * lScale, scale = plane.rmax * lScale / baseRadius) - } - } - is GDMLBoolSolid -> { - val first = solid.first.resolve(context.root) ?: error("") - val second = solid.second.resolve(context.root) ?: error("") - val type: CompositeType = when (solid) { - is GDMLUnion -> CompositeType.UNION - is GDMLSubtraction -> CompositeType.SUBTRACT - is GDMLIntersection -> CompositeType.INTERSECT - } - - return composite(type, name) { - addSolid(context, first) { - withPosition( - context.lUnit, - solid.resolveFirstPosition(context.root), - solid.resolveFirstRotation(context.root), - null - ) - } - addSolid(context, second) { - withPosition( - context.lUnit, - solid.resolvePosition(context.root), - solid.resolveRotation(context.root), - null - ) - } - } - } - else -> error("Renderer for $solid not supported yet") - }.apply(block) -} - -private val volumesName = "volumes".asName() - -private fun SolidGroup.addPhysicalVolume( - context: GDMLTransformer, - physVolume: GDMLPhysVolume -) { - val volume: GDMLGroup = physVolume.volumeref.resolve(context.root) - ?: error("Volume with ref ${physVolume.volumeref.ref} could not be resolved") - - when (context.volumeAction(volume)) { - GDMLTransformer.Action.ACCEPT -> { - val group = volume(context, volume) - this[physVolume.name ?: ""] = group.apply { - withPosition( - context.lUnit, - physVolume.resolvePosition(context.root), - physVolume.resolveRotation(context.root), - physVolume.resolveScale(context.root) - ) - } - } - GDMLTransformer.Action.CACHE -> { - val fullName = volumesName + volume.name.asName() - if (context.proto[fullName] == null) { - context.proto[fullName] = volume(context, volume) - } - - this[physVolume.name ?: ""] = Proxy(this, fullName).apply { - withPosition( - context.lUnit, - physVolume.resolvePosition(context.root), - physVolume.resolveRotation(context.root), - physVolume.resolveScale(context.root) - ) - } - } - GDMLTransformer.Action.REJECT -> { - //ignore - } - } -} - -private fun SolidGroup.addDivisionVolume( - context: GDMLTransformer, - divisionVolume: GDMLDivisionVolume -) { - val volume: GDMLGroup = divisionVolume.volumeref.resolve(context.root) - ?: error("Volume with ref ${divisionVolume.volumeref.ref} could not be resolved") - - //TODO add divisions - set( - Name.EMPTY, - volume( - context, - volume - ) - ) -} - -private val solidsName = "solids".asName() - -private fun volume( - context: GDMLTransformer, - group: GDMLGroup -): SolidGroup { - return SolidGroup().apply { - if (group is GDMLVolume) { - val solid = group.solidref.resolve(context.root) - ?: error("Solid with tag ${group.solidref.ref} for volume ${group.name} not defined") - - when (context.solidAction(solid)) { - GDMLTransformer.Action.ACCEPT -> { - addSolid(context, solid, solid.name) { - context.configureSolid(this, group, solid) - } - } - GDMLTransformer.Action.CACHE -> { - if (context.proto[solid.name] == null) { - context.proto.addSolid(context, solid, solid.name) { - context.configureSolid(this, group, solid) - } - } - ref(solid.name.asName(), solid.name) - } - GDMLTransformer.Action.REJECT -> { - //ignore - } - } - - when (val vol = group.placement) { - is GDMLPhysVolume -> addPhysicalVolume(context, vol) - is GDMLDivisionVolume -> addDivisionVolume(context, vol) - } - } - - group.physVolumes.forEach { physVolume -> - addPhysicalVolume(context, physVolume) - } - } -} - -fun GDML.toVision(block: GDMLTransformer.() -> Unit = {}): SolidGroup { - val context = GDMLTransformer(this).apply(block) - return context.finalize(volume(context, world)) -} - -/** - * Append gdml node to the group - */ -fun SolidGroup.gdml(gdml: GDML, key: String = "", transformer: GDMLTransformer.() -> Unit = {}) { - val visual = gdml.toVision(transformer) - //println(Visual3DPlugin.json.stringify(VisualGroup3D.serializer(), visual)) - set(key, visual) -} \ No newline at end of file diff --git a/visionforge-gdml/src/jsMain/kotlin/hep/dataforge/vision/gdml/gdmlJs.kt b/visionforge-gdml/src/jsMain/kotlin/hep/dataforge/vision/gdml/gdmlJs.kt new file mode 100644 index 00000000..44a36b6c --- /dev/null +++ b/visionforge-gdml/src/jsMain/kotlin/hep/dataforge/vision/gdml/gdmlJs.kt @@ -0,0 +1,8 @@ +package hep.dataforge.vision.gdml + +actual class Counter { + private var count: Int = 0 + actual fun get(): Int = count + + actual fun incrementAndGet(): Int = count++ +} \ No newline at end of file diff --git a/visionforge-gdml/src/jvmMain/kotlin/hep/dataforge/vision/gdml/visualGDMLJvm.kt b/visionforge-gdml/src/jvmMain/kotlin/hep/dataforge/vision/gdml/gdmlJVM.kt similarity index 85% rename from visionforge-gdml/src/jvmMain/kotlin/hep/dataforge/vision/gdml/visualGDMLJvm.kt rename to visionforge-gdml/src/jvmMain/kotlin/hep/dataforge/vision/gdml/gdmlJVM.kt index 0d47ea7a..1718cc74 100644 --- a/visionforge-gdml/src/jvmMain/kotlin/hep/dataforge/vision/gdml/visualGDMLJvm.kt +++ b/visionforge-gdml/src/jvmMain/kotlin/hep/dataforge/vision/gdml/gdmlJVM.kt @@ -5,6 +5,9 @@ import nl.adaptivity.xmlutil.StAXReader import scientifik.gdml.GDML import java.nio.file.Files import java.nio.file.Path +import java.util.concurrent.atomic.AtomicInteger + +actual typealias Counter = AtomicInteger fun GDML.Companion.readFile(file: Path): GDML { val xmlReader = StAXReader(Files.newInputStream(file), "UTF-8") @@ -15,4 +18,3 @@ fun SolidGroup.gdml(file: Path, key: String = "", transformer: GDMLTransformer.( val gdml = GDML.readFile(file) gdml(gdml, key, transformer) } - diff --git a/visionforge-gdml/src/jvmTest/kotlin/hep/dataforge/vision/gdml/TestConvertor.kt b/visionforge-gdml/src/jvmTest/kotlin/hep/dataforge/vision/gdml/TestConvertor.kt index d932ab0e..287553a1 100644 --- a/visionforge-gdml/src/jvmTest/kotlin/hep/dataforge/vision/gdml/TestConvertor.kt +++ b/visionforge-gdml/src/jvmTest/kotlin/hep/dataforge/vision/gdml/TestConvertor.kt @@ -10,11 +10,10 @@ class TestConvertor { @Test fun testBMNGeometry() { val stream = javaClass.getResourceAsStream("/gdml/BM@N.gdml") - val xmlReader = StAXReader(stream, "UTF-8") val xml = GDML.format.parse(GDML.serializer(), xmlReader) - val visual = xml.toVision() - println(visual.stringify()) + val vision = xml.toVision() + println(vision.stringify()) } @Test diff --git a/visionforge-gdml/src/jvmTest/kotlin/hep/dataforge/vision/gdml/bmanStatistics.kt b/visionforge-gdml/src/jvmTest/kotlin/hep/dataforge/vision/gdml/bmanStatistics.kt new file mode 100644 index 00000000..a8af85c6 --- /dev/null +++ b/visionforge-gdml/src/jvmTest/kotlin/hep/dataforge/vision/gdml/bmanStatistics.kt @@ -0,0 +1,34 @@ +package hep.dataforge.vision.gdml + +import hep.dataforge.vision.visitor.countDistinctBy +import hep.dataforge.vision.visitor.flowStatistics +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.withContext +import nl.adaptivity.xmlutil.StAXReader +import scientifik.gdml.GDML +import java.io.File + +suspend fun main() { + withContext(Dispatchers.Default) { + //val stream = SingleChildReducer::class.java.getResourceAsStream("/gdml/BM@N.gdml") + val stream = + File("D:\\Work\\Projects\\dataforge-vis\\visionforge-gdml\\src\\jvmTest\\resources\\gdml\\BM@N.gdml").inputStream() + + val xmlReader = StAXReader(stream, "UTF-8") + val xml = GDML.format.parse(GDML.serializer(), xmlReader) + val vision = xml.toVision() + + + vision.flowStatistics().countDistinctBy { it.type }.forEach { (depth, size) -> + println("$depth\t$size") + } + + println("***REDUCED***") + + vision.optimizeGdml() + + vision.flowStatistics().countDistinctBy { it.type }.forEach { (depth, size) -> + println("$depth\t$size") + } + } +} \ No newline at end of file diff --git a/visionforge-solid/src/commonMain/kotlin/hep/dataforge/vision/solid/Proxy.kt b/visionforge-solid/src/commonMain/kotlin/hep/dataforge/vision/solid/Proxy.kt index 53d65b0a..85d122c8 100644 --- a/visionforge-solid/src/commonMain/kotlin/hep/dataforge/vision/solid/Proxy.kt +++ b/visionforge-solid/src/commonMain/kotlin/hep/dataforge/vision/solid/Proxy.kt @@ -13,6 +13,9 @@ import kotlinx.serialization.Transient import kotlinx.serialization.UseSerializers import kotlin.collections.set + +class AbstractProxy + /** * A proxy [Solid] to reuse a template object */ @@ -39,8 +42,7 @@ class Proxy private constructor( get() = (parent as? SolidGroup)?.getPrototype(templateName) ?: error("Prototype with name $templateName not found in $parent") - override val styleSheet: StyleSheet - get() = parent?.styleSheet ?: StyleSheet(this) + override val styleSheet: StyleSheet get() = parent?.styleSheet ?: StyleSheet(this) override fun getProperty(name: Name, inherit: Boolean): MetaItem<*>? { return if (inherit) { diff --git a/visionforge-solid/src/commonMain/kotlin/hep/dataforge/vision/solid/Solid.kt b/visionforge-solid/src/commonMain/kotlin/hep/dataforge/vision/solid/Solid.kt index d1cfdaca..721d38ee 100644 --- a/visionforge-solid/src/commonMain/kotlin/hep/dataforge/vision/solid/Solid.kt +++ b/visionforge-solid/src/commonMain/kotlin/hep/dataforge/vision/solid/Solid.kt @@ -103,9 +103,9 @@ interface Solid : Vision { * Count number of layers to the top object. Return 1 if this is top layer */ var Solid.layer: Int - get() = getItem(LAYER_KEY).int ?: 0 + get() = properties?.getItem(LAYER_KEY).int ?: 0 set(value) { - setItem(LAYER_KEY, value.asValue()) + config[LAYER_KEY] = value.asValue() } fun Renderer.render(meta: Meta = Meta.EMPTY, action: SolidGroup.() -> Unit) = diff --git a/visionforge-solid/src/jsMain/kotlin/hep/dataforge/vision/solid/three/MeshThreeFactory.kt b/visionforge-solid/src/jsMain/kotlin/hep/dataforge/vision/solid/three/MeshThreeFactory.kt index f3b2d30f..eb7192c0 100644 --- a/visionforge-solid/src/jsMain/kotlin/hep/dataforge/vision/solid/three/MeshThreeFactory.kt +++ b/visionforge-solid/src/jsMain/kotlin/hep/dataforge/vision/solid/three/MeshThreeFactory.kt @@ -35,7 +35,7 @@ abstract class MeshThreeFactory( //val meshMeta: Meta = obj.properties[Material3D.MATERIAL_KEY]?.node ?: Meta.empty - val mesh = Mesh(geometry, getMaterial(obj)).apply { + val mesh = Mesh(geometry, getMaterial(obj, true)).apply { matrixAutoUpdate = false applyEdges(obj) applyWireFrame(obj) @@ -50,7 +50,7 @@ abstract class MeshThreeFactory( } //add listener to object properties - obj.onPropertyChange(this) { name-> + obj.onPropertyChange(this) { name -> when { name.startsWith(Solid.GEOMETRY_KEY) -> { val oldGeometry = mesh.geometry as BufferGeometry @@ -80,22 +80,28 @@ abstract class MeshThreeFactory( } fun Mesh.applyEdges(obj: Solid) { - children.find { it.name == "@edges" }?.let { - remove(it) - (it as LineSegments).dispose() - } + val edges = children.find { it.name == "@edges" } as? LineSegments //inherited edges definition, enabled by default if (obj.getItem(MeshThreeFactory.EDGES_ENABLED_KEY).boolean != false) { - - val material = ThreeMaterials.getLineMaterial(obj.getItem(MeshThreeFactory.EDGES_MATERIAL_KEY).node) - add( - LineSegments( - EdgesGeometry(geometry as BufferGeometry), - material - ).apply { - name = "@edges" - } - ) + val bufferGeometry = geometry as? BufferGeometry ?: return + val material = ThreeMaterials.getLineMaterial(obj.getItem(MeshThreeFactory.EDGES_MATERIAL_KEY).node, true) + if (edges == null) { + add( + LineSegments( + EdgesGeometry(bufferGeometry), + material + ).apply { + name = "@edges" + } + ) + } else { + edges.material = material + } + } else { + edges?.let { + remove(it) + it.dispose() + } } } @@ -106,10 +112,11 @@ fun Mesh.applyWireFrame(obj: Solid) { } //inherited wireframe definition, disabled by default if (obj.getItem(MeshThreeFactory.WIREFRAME_ENABLED_KEY).boolean == true) { - val material = ThreeMaterials.getLineMaterial(obj.getItem(MeshThreeFactory.WIREFRAME_MATERIAL_KEY).node) + val bufferGeometry = geometry as? BufferGeometry ?: return + val material = ThreeMaterials.getLineMaterial(obj.getItem(MeshThreeFactory.WIREFRAME_MATERIAL_KEY).node, true) add( LineSegments( - WireframeGeometry(geometry as BufferGeometry), + WireframeGeometry(bufferGeometry), material ).apply { name = "@wireframe" diff --git a/visionforge-solid/src/jsMain/kotlin/hep/dataforge/vision/solid/three/ThreeFactory.kt b/visionforge-solid/src/jsMain/kotlin/hep/dataforge/vision/solid/three/ThreeFactory.kt index 8bbd55a3..8b83ef16 100644 --- a/visionforge-solid/src/jsMain/kotlin/hep/dataforge/vision/solid/three/ThreeFactory.kt +++ b/visionforge-solid/src/jsMain/kotlin/hep/dataforge/vision/solid/three/ThreeFactory.kt @@ -58,7 +58,7 @@ fun Object3D.updatePosition(obj: Vision) { */ fun Object3D.updateProperty(source: Vision, propertyName: Name) { if (this is Mesh && propertyName.startsWith(MATERIAL_KEY)) { - this.material = getMaterial(source) + this.material = getMaterial(source, false) } else if ( propertyName.startsWith(Solid.POSITION_KEY) || propertyName.startsWith(Solid.ROTATION) diff --git a/visionforge-solid/src/jsMain/kotlin/hep/dataforge/vision/solid/three/ThreeLabelFactory.kt b/visionforge-solid/src/jsMain/kotlin/hep/dataforge/vision/solid/three/ThreeLabelFactory.kt index 60b0352a..f6c677c4 100644 --- a/visionforge-solid/src/jsMain/kotlin/hep/dataforge/vision/solid/three/ThreeLabelFactory.kt +++ b/visionforge-solid/src/jsMain/kotlin/hep/dataforge/vision/solid/three/ThreeLabelFactory.kt @@ -21,7 +21,7 @@ object ThreeLabelFactory : ThreeFactory { height = 1 curveSegments = 1 }) - return Mesh(textGeo, getMaterial(obj)).apply { + return Mesh(textGeo, getMaterial(obj,true)).apply { updatePosition(obj) obj.onPropertyChange(this@ThreeLabelFactory) { _ -> //TODO diff --git a/visionforge-solid/src/jsMain/kotlin/hep/dataforge/vision/solid/three/ThreeLineFactory.kt b/visionforge-solid/src/jsMain/kotlin/hep/dataforge/vision/solid/three/ThreeLineFactory.kt index c0b67e25..a032f527 100644 --- a/visionforge-solid/src/jsMain/kotlin/hep/dataforge/vision/solid/three/ThreeLineFactory.kt +++ b/visionforge-solid/src/jsMain/kotlin/hep/dataforge/vision/solid/three/ThreeLineFactory.kt @@ -18,7 +18,7 @@ object ThreeLineFactory : ThreeFactory { vertices = obj.points.toTypedArray() } - val material = ThreeMaterials.getLineMaterial(obj.getItem(MeshThreeFactory.EDGES_MATERIAL_KEY).node) + val material = ThreeMaterials.getLineMaterial(obj.getItem(MeshThreeFactory.EDGES_MATERIAL_KEY).node, true) material.linewidth = obj.thickness.toDouble() material.color = obj.color?.let { Color(it) } ?: DEFAULT_LINE_COLOR diff --git a/visionforge-solid/src/jsMain/kotlin/hep/dataforge/vision/solid/three/ThreeMaterials.kt b/visionforge-solid/src/jsMain/kotlin/hep/dataforge/vision/solid/three/ThreeMaterials.kt index a2da8611..7566e136 100644 --- a/visionforge-solid/src/jsMain/kotlin/hep/dataforge/vision/solid/three/ThreeMaterials.kt +++ b/visionforge-solid/src/jsMain/kotlin/hep/dataforge/vision/solid/three/ThreeMaterials.kt @@ -33,18 +33,27 @@ object ThreeMaterials { linewidth = 8.0 } - fun getLineMaterial(meta: Meta?): LineBasicMaterial { + private val lineMaterialCache = HashMap() + + private fun buildLineMaterial(meta: Meta): LineBasicMaterial = LineBasicMaterial().apply { + color = meta[SolidMaterial.COLOR_KEY]?.getColor() ?: DEFAULT_LINE_COLOR + opacity = meta[SolidMaterial.OPACITY_KEY].double ?: 1.0 + transparent = opacity < 1.0 + linewidth = meta["thickness"].double ?: 1.0 + } + + fun getLineMaterial(meta: Meta?, cache: Boolean): LineBasicMaterial { if (meta == null) return DEFAULT_LINE - return LineBasicMaterial().apply { - color = meta[SolidMaterial.COLOR_KEY]?.getColor() ?: DEFAULT_LINE_COLOR - opacity = meta[SolidMaterial.OPACITY_KEY].double ?: 1.0 - transparent = opacity < 1.0 - linewidth = meta["thickness"].double ?: 1.0 + return if (cache) { + lineMaterialCache.getOrPut(meta) { buildLineMaterial(meta) } + } else { + buildLineMaterial(meta) } } - fun getMaterial(vision3D: Vision): Material { - val meta = vision3D.getItem(SolidMaterial.MATERIAL_KEY).node ?: return DEFAULT + private val materialCache = HashMap() + + private fun buildMaterial(meta: Meta): Material { return if (meta[SolidMaterial.SPECULAR_COLOR_KEY] != null) { MeshPhongMaterial().apply { color = meta[SolidMaterial.COLOR_KEY]?.getColor() ?: DEFAULT_COLOR @@ -65,6 +74,15 @@ object ThreeMaterials { } } + fun getMaterial(vision3D: Vision, cache: Boolean): Material { + val meta = vision3D.getItem(SolidMaterial.MATERIAL_KEY).node ?: return DEFAULT + return if (cache) { + materialCache.getOrPut(meta) { buildMaterial(meta) } + } else { + buildMaterial(meta) + } + } + } /** diff --git a/visionforge-solid/src/jsMain/kotlin/hep/dataforge/vision/solid/three/ThreePlugin.kt b/visionforge-solid/src/jsMain/kotlin/hep/dataforge/vision/solid/three/ThreePlugin.kt index a3af79d4..d8f467fe 100644 --- a/visionforge-solid/src/jsMain/kotlin/hep/dataforge/vision/solid/three/ThreePlugin.kt +++ b/visionforge-solid/src/jsMain/kotlin/hep/dataforge/vision/solid/three/ThreePlugin.kt @@ -70,7 +70,7 @@ class ThreePlugin : AbstractPlugin() { obj.onChildrenChange(this) { name, child -> if (name.isEmpty()) { - logger.error { "Children change with empty namr on $group" } + logger.error { "Children change with empty name on $group" } return@onChildrenChange } diff --git a/visionforge-solid/src/jsMain/kotlin/hep/dataforge/vision/solid/three/ThreeProxyFactory.kt b/visionforge-solid/src/jsMain/kotlin/hep/dataforge/vision/solid/three/ThreeProxyFactory.kt index 9ae86b4d..2fd83dfa 100644 --- a/visionforge-solid/src/jsMain/kotlin/hep/dataforge/vision/solid/three/ThreeProxyFactory.kt +++ b/visionforge-solid/src/jsMain/kotlin/hep/dataforge/vision/solid/three/ThreeProxyFactory.kt @@ -4,12 +4,26 @@ import hep.dataforge.names.toName import hep.dataforge.vision.solid.Proxy import hep.dataforge.vision.solid.Proxy.Companion.PROXY_CHILD_PROPERTY_PREFIX import hep.dataforge.vision.solid.Solid +import info.laht.threekt.core.BufferGeometry import info.laht.threekt.core.Object3D +import info.laht.threekt.objects.Mesh +import kotlin.reflect.KClass class ThreeProxyFactory(val three: ThreePlugin) : ThreeFactory { private val cache = HashMap() - override val type = Proxy::class + override val type: KClass = Proxy::class + + private fun Object3D.replicate(): Object3D { + return when (this) { + is Mesh -> Mesh(geometry as BufferGeometry, material) + else -> clone(false) + }.also { obj: Object3D -> + children.forEach { child: Object3D -> + obj.add(child.replicate()) + } + } + } override fun invoke(obj: Proxy): Object3D { val template = obj.prototype @@ -17,16 +31,16 @@ class ThreeProxyFactory(val three: ThreePlugin) : ThreeFactory { three.buildObject3D(template) } - //val mesh = Mesh(templateMesh.geometry as BufferGeometry, templateMesh.material) - val object3D = cachedObject.clone() + val object3D: Object3D = cachedObject.replicate() + object3D.updatePosition(obj) - obj.onPropertyChange(this) { name-> + obj.onPropertyChange(this) { name -> if (name.first()?.body == PROXY_CHILD_PROPERTY_PREFIX) { val childName = name.first()?.index?.toName() ?: error("Wrong syntax for proxy child property: '$name'") val propertyName = name.cutFirst() val proxyChild = obj[childName] ?: error("Proxy child with name '$childName' not found") - val child = object3D.findChild(childName)?: error("Object child with name '$childName' not found") + val child = object3D.findChild(childName) ?: error("Object child with name '$childName' not found") child.updateProperty(proxyChild, propertyName) } else { object3D.updateProperty(obj, name) diff --git a/visionforge-solid/src/jsMain/kotlin/info/laht/threekt/objects/LineSegments.kt b/visionforge-solid/src/jsMain/kotlin/info/laht/threekt/objects/LineSegments.kt index 3925c7fb..b5a83ff0 100644 --- a/visionforge-solid/src/jsMain/kotlin/info/laht/threekt/objects/LineSegments.kt +++ b/visionforge-solid/src/jsMain/kotlin/info/laht/threekt/objects/LineSegments.kt @@ -34,4 +34,7 @@ import info.laht.threekt.materials.Material open external class LineSegments(geometry: BufferGeometry, material: Material) : Object3D { constructor(geometry: Geometry, material: Material) + + var geometry: BufferGeometry + var material: Material } \ No newline at end of file From b362f86f9bc89abaac2c41c87bad817081092d0f Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Wed, 26 Aug 2020 21:12:39 +0300 Subject: [PATCH 004/151] GDML optimization --- .../hep/dataforge/vision/gdml/demo/cubes.kt | 2 +- .../dataforge/vision/gdml/GDMLVisualTest.kt | 16 +- .../kotlin/hep/dataforge/vision/StyleSheet.kt | 3 +- .../kotlin/hep/dataforge/vision/Vision.kt | 3 +- .../dataforge/vision/gdml/GDMLTransformer.kt | 129 ++++++------- .../hep/dataforge/vision/solid/Proxy.kt | 172 ++++++++---------- .../hep/dataforge/vision/solid/SolidGroup.kt | 9 +- .../vision/solid/three/MeshThreeFactory.kt | 22 ++- .../vision/solid/three/ThreeFactory.kt | 12 -- .../vision/solid/three/ThreeProxyFactory.kt | 28 +-- .../vision/solid/three/outputConfig.kt | 2 + .../kotlin/info/laht/threekt/objects/Mesh.kt | 4 +- 12 files changed, 179 insertions(+), 223 deletions(-) diff --git a/demo/gdml/src/commonMain/kotlin/hep/dataforge/vision/gdml/demo/cubes.kt b/demo/gdml/src/commonMain/kotlin/hep/dataforge/vision/gdml/demo/cubes.kt index e0666f2a..1f0b8cf9 100644 --- a/demo/gdml/src/commonMain/kotlin/hep/dataforge/vision/gdml/demo/cubes.kt +++ b/demo/gdml/src/commonMain/kotlin/hep/dataforge/vision/gdml/demo/cubes.kt @@ -20,7 +20,7 @@ fun cubes(): GDML = GDML { val circle = volume("composite", boxMaterial, smallBox.ref()) { for (i in 0 until 6) { physVolume(segmentVolume) { - name = "segment$i" + name = "segment_$i" positionref = center.ref() rotation { z = 60 * i diff --git a/demo/gdml/src/commonTest/kotlin/hep/dataforge/vision/gdml/GDMLVisualTest.kt b/demo/gdml/src/commonTest/kotlin/hep/dataforge/vision/gdml/GDMLVisualTest.kt index ed3710e3..59545bdf 100644 --- a/demo/gdml/src/commonTest/kotlin/hep/dataforge/vision/gdml/GDMLVisualTest.kt +++ b/demo/gdml/src/commonTest/kotlin/hep/dataforge/vision/gdml/GDMLVisualTest.kt @@ -10,11 +10,21 @@ import kotlin.test.Test import kotlin.test.assertEquals class GDMLVisualTest { + val gdml = cubes() + +// @Test +// fun testCubesStyles(){ +// val cubes = gdml.toVision() +// val segment = cubes["composite000.segment_0".toName()] as Solid +// println(segment.styles) +// println(segment.material) +// } + + @Test fun testPrototypeProperty() { - val gdml = cubes() val visual = gdml.toVision() - visual["composite000.segment0".toName()]?.setItem(SolidMaterial.MATERIAL_COLOR_KEY, "red".asValue()) - assertEquals("red", visual["composite000.segment0".toName()]?.getItem(SolidMaterial.MATERIAL_COLOR_KEY).string) + visual["composite000.segment_0".toName()]?.setItem(SolidMaterial.MATERIAL_COLOR_KEY, "red".asValue()) + assertEquals("red", visual["composite000.segment_0".toName()]?.getItem(SolidMaterial.MATERIAL_COLOR_KEY).string) } } \ No newline at end of file diff --git a/visionforge-core/src/commonMain/kotlin/hep/dataforge/vision/StyleSheet.kt b/visionforge-core/src/commonMain/kotlin/hep/dataforge/vision/StyleSheet.kt index 1ff736c9..d4199657 100644 --- a/visionforge-core/src/commonMain/kotlin/hep/dataforge/vision/StyleSheet.kt +++ b/visionforge-core/src/commonMain/kotlin/hep/dataforge/vision/StyleSheet.kt @@ -84,7 +84,6 @@ class StyleSheet private constructor(private val styleMap: MutableMap get() = properties[STYLE_KEY].stringList set(value) { - setItem(STYLE_KEY,value.map { it.asValue() }.asValue()) + config[STYLE_KEY] = value } companion object { diff --git a/visionforge-gdml/src/commonMain/kotlin/hep/dataforge/vision/gdml/GDMLTransformer.kt b/visionforge-gdml/src/commonMain/kotlin/hep/dataforge/vision/gdml/GDMLTransformer.kt index 82413d93..ad48480b 100644 --- a/visionforge-gdml/src/commonMain/kotlin/hep/dataforge/vision/gdml/GDMLTransformer.kt +++ b/visionforge-gdml/src/commonMain/kotlin/hep/dataforge/vision/gdml/GDMLTransformer.kt @@ -6,7 +6,6 @@ import hep.dataforge.names.Name import hep.dataforge.names.asName import hep.dataforge.names.plus import hep.dataforge.names.toName -import hep.dataforge.vision.get import hep.dataforge.vision.set import hep.dataforge.vision.solid.* import hep.dataforge.vision.solid.SolidMaterial.Companion.MATERIAL_COLOR_KEY @@ -27,6 +26,7 @@ class GDMLTransformer(val root: GDML) { } var lUnit: LUnit = LUnit.MM + var aUnit: AUnit = AUnit.RADIAN var solidAction: (GDMLSolid) -> Action = { Action.CACHE } var volumeAction: (GDMLGroup) -> Action = { Action.CACHE } @@ -65,10 +65,6 @@ class GDMLTransformer(val root: GDML) { obj.solidConfiguration(parent, solid) } -// -// internal fun solidAdded(solid: GDMLSolid) { -// solidCounter[solid.name] = (solidCounter[solid.name] ?: 0) + 1 -// } var onFinish: GDMLTransformer.() -> Unit = {} @@ -94,6 +90,7 @@ class GDMLTransformer(val root: GDML) { private fun Solid.withPosition( lUnit: LUnit, + aUnit: AUnit = AUnit.RADIAN, newPos: GDMLPosition? = null, newRotation: GDMLRotation? = null, newScale: GDMLScale? = null @@ -105,7 +102,7 @@ private fun Solid.withPosition( } } newRotation?.let { - val point = Point3D(it.x(), it.y(), it.z()) + val point = Point3D(it.x(aUnit), it.y(aUnit), it.z(aUnit)) if (rotation != null || point != World.ZERO) { rotation = point } @@ -120,6 +117,13 @@ private fun Solid.withPosition( //TODO convert units if needed } +private fun Solid.withPosition(context: GDMLTransformer, physVolume: GDMLPhysVolume) = withPosition( + context.lUnit, context.aUnit, + physVolume.resolvePosition(context.root), + physVolume.resolveRotation(context.root), + physVolume.resolveScale(context.root) +) + @Suppress("NOTHING_TO_INLINE") private inline operator fun Number.times(d: Double) = toDouble() * d @@ -129,8 +133,7 @@ private inline operator fun Number.times(f: Float) = toFloat() * f private fun SolidGroup.addSolid( context: GDMLTransformer, solid: GDMLSolid, - name: String = "", - block: Solid.() -> Unit = {} + name: String = "" ): Solid { //context.solidAdded(solid) val lScale = solid.lscale(context.lUnit) @@ -168,11 +171,10 @@ private fun SolidGroup.addSolid( } is GDMLScaledSolid -> { //Add solid with modified scale - val innerSolid = solid.solidref.resolve(context.root) + val innerSolid: GDMLSolid = solid.solidref.resolve(context.root) ?: error("Solid with tag ${solid.solidref.ref} for scaled solid ${solid.name} not defined") - addSolid(context, innerSolid, name) { - block() + addSolid(context, innerSolid, name).apply { scaleX *= solid.scale.x.toFloat() scaleY *= solid.scale.y.toFloat() scaleZ = solid.scale.z.toFloat() @@ -199,8 +201,8 @@ private fun SolidGroup.addSolid( } } is GDMLBoolSolid -> { - val first = solid.first.resolve(context.root) ?: error("") - val second = solid.second.resolve(context.root) ?: error("") + val first: GDMLSolid = solid.first.resolve(context.root) ?: error("") + val second: GDMLSolid = solid.second.resolve(context.root) ?: error("") val type: CompositeType = when (solid) { is GDMLUnion -> CompositeType.UNION is GDMLSubtraction -> CompositeType.SUBTRACT @@ -208,54 +210,51 @@ private fun SolidGroup.addSolid( } return composite(type, name) { - addSolid(context, first) { - withPosition( - context.lUnit, - solid.resolveFirstPosition(context.root), - solid.resolveFirstRotation(context.root), - null - ) - } - addSolid(context, second) { - withPosition( - context.lUnit, - solid.resolvePosition(context.root), - solid.resolveRotation(context.root), - null - ) - } + addSolid(context, first).withPosition( + context.lUnit, context.aUnit, + solid.resolveFirstPosition(context.root), + solid.resolveFirstRotation(context.root), + null + ) + + addSolid(context, second).withPosition( + context.lUnit, context.aUnit, + solid.resolvePosition(context.root), + solid.resolveRotation(context.root), + null + ) + } } else -> error("Renderer for $solid not supported yet") - }.apply(block) + } } +private val solidsName = "solids".asName() + private fun SolidGroup.addSolidWithCaching( context: GDMLTransformer, solid: GDMLSolid, - volume: GDMLVolume, name: String = solid.name -) { - when (context.solidAction(solid)) { +): Solid? { + return when (context.solidAction(solid)) { GDMLTransformer.Action.ACCEPT -> { - addSolid(context, solid, name) { - context.configureSolid(this, volume, solid) - } + addSolid(context, solid, name) } GDMLTransformer.Action.CACHE -> { - if (context.proto[solid.name] == null) { - context.proto.addSolid(context, solid, name) { - context.configureSolid(this, volume, solid) - } + val fullName = solidsName + solid.name.asName() + if (context.proto[fullName] == null) { + val parent = (context.proto[solidsName] as? SolidGroup) ?: context.proto.group(solidsName) + parent.addSolid(context, solid, solid.name) } - ref(solid.name.asName(), name) + ref(fullName, name) } GDMLTransformer.Action.REJECT -> { //ignore + null } } - } private val volumesName = "volumes".asName() @@ -268,31 +267,20 @@ private fun SolidGroup.addPhysicalVolume( ?: error("Volume with ref ${physVolume.volumeref.ref} could not be resolved") // a special case for single solid volume -// if (volume is GDMLVolume && volume.physVolumes.isEmpty() && volume.placement == null) { -// val solid = volume.solidref.resolve(context.root) -// ?: error("Solid with tag ${volume.solidref.ref} for volume ${volume.name} not defined") -// addSolidWithCaching(context, solid, volume, physVolume.name ?: "").apply { -// withPosition( -// context.lUnit, -// physVolume.resolvePosition(context.root), -// physVolume.resolveRotation(context.root), -// physVolume.resolveScale(context.root) -// ) -// } -// return -// } + if (volume is GDMLVolume && volume.physVolumes.isEmpty() && volume.placement == null) { + val solid = volume.solidref.resolve(context.root) + ?: error("Solid with tag ${volume.solidref.ref} for volume ${volume.name} not defined") + addSolidWithCaching(context, solid, physVolume.name ?: "")?.apply { + context.configureSolid(this, volume, solid) + withPosition(context, physVolume) + } + return + } when (context.volumeAction(volume)) { GDMLTransformer.Action.ACCEPT -> { val group: SolidGroup = volume(context, volume) - this[physVolume.name ?: ""] = group.apply { - withPosition( - context.lUnit, - physVolume.resolvePosition(context.root), - physVolume.resolveRotation(context.root), - physVolume.resolveScale(context.root) - ) - } + this[physVolume.name ?: ""] = group.withPosition(context, physVolume) } GDMLTransformer.Action.CACHE -> { val fullName = volumesName + volume.name.asName() @@ -300,14 +288,7 @@ private fun SolidGroup.addPhysicalVolume( context.proto[fullName] = volume(context, volume) } - this[physVolume.name ?: ""] = Proxy(this, fullName).apply { - withPosition( - context.lUnit, - physVolume.resolvePosition(context.root), - physVolume.resolveRotation(context.root), - physVolume.resolveScale(context.root) - ) - } + this[physVolume.name ?: ""] = Proxy(this, fullName).withPosition(context, physVolume) } GDMLTransformer.Action.REJECT -> { //ignore @@ -326,8 +307,6 @@ private fun SolidGroup.addDivisionVolume( set(Name.EMPTY, volume(context, volume)) } -//private val solidsName = "solids".asName() - private fun volume( context: GDMLTransformer, group: GDMLGroup @@ -336,7 +315,9 @@ private fun volume( val solid: GDMLSolid = group.solidref.resolve(context.root) ?: error("Solid with tag ${group.solidref.ref} for volume ${group.name} not defined") - addSolidWithCaching(context, solid, group) + addSolidWithCaching(context, solid)?.apply { + context.configureSolid(this, group, solid) + } when (val vol: GDMLPlacement? = group.placement) { is GDMLPhysVolume -> addPhysicalVolume(context, vol) diff --git a/visionforge-solid/src/commonMain/kotlin/hep/dataforge/vision/solid/Proxy.kt b/visionforge-solid/src/commonMain/kotlin/hep/dataforge/vision/solid/Proxy.kt index 85d122c8..bf2369a7 100644 --- a/visionforge-solid/src/commonMain/kotlin/hep/dataforge/vision/solid/Proxy.kt +++ b/visionforge-solid/src/commonMain/kotlin/hep/dataforge/vision/solid/Proxy.kt @@ -5,7 +5,6 @@ package hep.dataforge.vision.solid import hep.dataforge.meta.* import hep.dataforge.meta.descriptors.NodeDescriptor import hep.dataforge.names.* -import hep.dataforge.values.asValue import hep.dataforge.vision.* import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable @@ -13,36 +12,8 @@ import kotlinx.serialization.Transient import kotlinx.serialization.UseSerializers import kotlin.collections.set - -class AbstractProxy - -/** - * A proxy [Solid] to reuse a template object - */ -@Serializable -@SerialName("solid.proxy") -class Proxy private constructor( - val templateName: Name -) : AbstractVision(), VisionGroup, Solid { - - constructor(parent: SolidGroup, templateName: Name) : this(templateName) { - this.parent = parent - } - - override var position: Point3D? = null - override var rotation: Point3D? = null - override var scale: Point3D? = null - - override var properties: Config? = null - - /** - * Recursively search for defined template in the parent - */ - val prototype: Solid - get() = (parent as? SolidGroup)?.getPrototype(templateName) - ?: error("Prototype with name $templateName not found in $parent") - - override val styleSheet: StyleSheet get() = parent?.styleSheet ?: StyleSheet(this) +abstract class AbstractProxy : AbstractVision(), VisionGroup { + abstract val prototype: Vision override fun getProperty(name: Name, inherit: Boolean): MetaItem<*>? { return if (inherit) { @@ -61,24 +32,11 @@ class Proxy private constructor( } } - override val children: Map - get() = (prototype as? VisionGroup)?.children - ?.filter { !it.key.toString().startsWith("@") } - ?.mapValues { - ProxyChild(it.key.asName()) - } ?: emptyMap() - - @Transient - private val propertyCache: HashMap = HashMap() - - fun childPropertyName(childName: Name, propertyName: Name): Name { - return NameToken(PROXY_CHILD_PROPERTY_PREFIX, childName.toString()) + propertyName - } - - private fun prototypeFor(name: Name): Vision { - return (prototype as? VisionGroup)?.get(name) - ?: error("Prototype with name $name not found in $this") - } + override var styles: List + get() = properties[Vision.STYLE_KEY].stringList + prototype.styles + set(value) { + config[Vision.STYLE_KEY] = value + } override fun getAllProperties(): Laminate = Laminate(properties, allStyles, prototype.getAllProperties(), parent?.getAllProperties()) @@ -87,29 +45,77 @@ class Proxy private constructor( //do nothing } + override val descriptor: NodeDescriptor? get() = prototype.descriptor +} + +/** + * A proxy [Solid] to reuse a template object + */ +@Serializable +@SerialName("solid.proxy") +class Proxy private constructor( + val templateName: Name +) : AbstractProxy(), Solid { + + constructor(parent: SolidGroup, templateName: Name) : this(templateName) { + this.parent = parent + } + + override var position: Point3D? = null + override var rotation: Point3D? = null + override var scale: Point3D? = null + + override var properties: Config? = null + + /** + * Recursively search for defined template in the parent + */ + override val prototype: Solid + get() = (parent as? SolidGroup)?.getPrototype(templateName) + ?: error("Prototype with name $templateName not found in $parent") + + override val styleSheet: StyleSheet get() = parent?.styleSheet ?: StyleSheet(this) + + @Transient + private val propertyCache: HashMap = HashMap() + + + override val children: Map + get() = (prototype as? VisionGroup)?.children + ?.filter { !it.key.toString().startsWith("@") } + ?.mapValues { + ProxyChild(it.key.asName()) + } ?: emptyMap() + + private fun childPropertyName(childName: Name, propertyName: Name): Name { + return NameToken(PROXY_CHILD_PROPERTY_PREFIX, childName.toString()) + propertyName + } + + private fun prototypeFor(name: Name): Vision { + return (prototype as? VisionGroup)?.get(name) + ?: error("Prototype with name $name not found in $this") + } + + override val descriptor: NodeDescriptor? get() = prototype.descriptor + //override fun findAllStyles(): Laminate = Laminate((styles + prototype.styles).mapNotNull { findStyle(it) }) - override var styles: List - get() = properties[Vision.STYLE_KEY].stringList + prototype.styles - set(value) { - setItem(Vision.STYLE_KEY, value.map { it.asValue() }.asValue()) - } + /** + * A ProxyChild is created temporarily only to interact with properties, it does not store any values + * (properties are stored in external cache) and created and destroyed on-demand). + */ + inner class ProxyChild(val name: Name) : AbstractProxy() { - override val descriptor: NodeDescriptor? - get() = prototype.descriptor - - inner class ProxyChild(val name: Name) : AbstractVision(), VisionGroup { - - val prototype: Vision get() = prototypeFor(name) + override val prototype: Vision get() = prototypeFor(name) override val styleSheet: StyleSheet get() = this@Proxy.styleSheet override val children: Map - get() = (prototype as? VisionGroup)?.children?.mapValues { (key, _) -> - ProxyChild( - name + key.asName() - ) - } ?: emptyMap() + get() = (prototype as? VisionGroup)?.children + ?.filter { !it.key.toString().startsWith("@") } + ?.mapValues { (key, _) -> + ProxyChild(name + key.asName()) + } ?: emptyMap() override var properties: Config? get() = propertyCache[name] @@ -128,39 +134,6 @@ class Proxy private constructor( } } - override fun getProperty(name: Name, inherit: Boolean): MetaItem<*>? { - return if (inherit) { - sequence { - yield(properties?.get(name)) - yieldAll(getStyleItems(name)) - yield(prototype.getItem(name)) - yield(parent?.getProperty(name, inherit)) - }.merge() - } else { - sequence { - yield(properties?.get(name)) - yieldAll(getStyleItems(name)) - yield(prototype.getProperty(name, false)) - }.merge() - } - } - - override fun attachChildren() { - //do nothing - } - - override fun getAllProperties(): Laminate = - Laminate(properties, allStyles, prototype.getAllProperties(), parent?.getAllProperties()) - - - override var styles: List - get() = properties[Vision.STYLE_KEY].stringList + prototype.styles - set(value) { - setItem(Vision.STYLE_KEY, value.map { it.asValue() }.asValue()) - } - - override val descriptor: NodeDescriptor? - get() = prototype.descriptor } companion object { @@ -170,8 +143,7 @@ class Proxy private constructor( val Vision.prototype: Vision get() = when (this) { - is Proxy -> prototype - is Proxy.ProxyChild -> prototype + is AbstractProxy -> prototype else -> this } diff --git a/visionforge-solid/src/commonMain/kotlin/hep/dataforge/vision/solid/SolidGroup.kt b/visionforge-solid/src/commonMain/kotlin/hep/dataforge/vision/solid/SolidGroup.kt index e7f17c9b..83e2deff 100644 --- a/visionforge-solid/src/commonMain/kotlin/hep/dataforge/vision/solid/SolidGroup.kt +++ b/visionforge-solid/src/commonMain/kotlin/hep/dataforge/vision/solid/SolidGroup.kt @@ -99,13 +99,14 @@ fun SolidGroup(block: SolidGroup.() -> Unit): SolidGroup { tailrec fun PrototypeHolder.getPrototype(name: Name): Solid? = prototypes?.get(name) as? Solid ?: (parent as? PrototypeHolder)?.getPrototype(name) +fun MutableVisionGroup.group(name: Name = Name.EMPTY, action: SolidGroup.() -> Unit = {}): SolidGroup = + SolidGroup().apply(action).also { set(name, it) } + /** * Define a group with given [name], attach it to this parent and return it. */ -fun MutableVisionGroup.group(name: String = "", action: SolidGroup.() -> Unit = {}): SolidGroup = - SolidGroup().apply(action).also { - set(name, it) - } +fun MutableVisionGroup.group(name: String, action: SolidGroup.() -> Unit = {}): SolidGroup = + SolidGroup().apply(action).also { set(name, it) } /** * A special class which works as a holder for prototypes diff --git a/visionforge-solid/src/jsMain/kotlin/hep/dataforge/vision/solid/three/MeshThreeFactory.kt b/visionforge-solid/src/jsMain/kotlin/hep/dataforge/vision/solid/three/MeshThreeFactory.kt index eb7192c0..ac153ab5 100644 --- a/visionforge-solid/src/jsMain/kotlin/hep/dataforge/vision/solid/three/MeshThreeFactory.kt +++ b/visionforge-solid/src/jsMain/kotlin/hep/dataforge/vision/solid/three/MeshThreeFactory.kt @@ -35,19 +35,11 @@ abstract class MeshThreeFactory( //val meshMeta: Meta = obj.properties[Material3D.MATERIAL_KEY]?.node ?: Meta.empty - val mesh = Mesh(geometry, getMaterial(obj, true)).apply { + val mesh = Mesh(geometry, null).apply{ matrixAutoUpdate = false - applyEdges(obj) - applyWireFrame(obj) - //set position for mesh updatePosition(obj) - - layers.enable(obj.layer) - children.forEach { - it.layers.enable(obj.layer) - } - } + }.applyProperties(obj) //add listener to object properties obj.onPropertyChange(this) { name -> @@ -79,6 +71,16 @@ abstract class MeshThreeFactory( } } +fun Mesh.applyProperties(obj: Solid): Mesh = apply{ + material = getMaterial(obj, true) + applyEdges(obj) + applyWireFrame(obj) + layers.enable(obj.layer) + children.forEach { + it.layers.enable(obj.layer) + } +} + fun Mesh.applyEdges(obj: Solid) { val edges = children.find { it.name == "@edges" } as? LineSegments //inherited edges definition, enabled by default diff --git a/visionforge-solid/src/jsMain/kotlin/hep/dataforge/vision/solid/three/ThreeFactory.kt b/visionforge-solid/src/jsMain/kotlin/hep/dataforge/vision/solid/three/ThreeFactory.kt index 8b83ef16..c432fbd3 100644 --- a/visionforge-solid/src/jsMain/kotlin/hep/dataforge/vision/solid/three/ThreeFactory.kt +++ b/visionforge-solid/src/jsMain/kotlin/hep/dataforge/vision/solid/three/ThreeFactory.kt @@ -41,18 +41,6 @@ fun Object3D.updatePosition(obj: Vision) { } } -///** -// * Unsafe invocation of a factory -// */ -//operator fun ThreeFactory.invoke(obj: Any): Object3D { -// if (type.isInstance(obj)) { -// @Suppress("UNCHECKED_CAST") -// return invoke(obj as T) -// } else { -// error("The object of type ${obj::class} could not be rendered by this factory") -// } -//} - /** * Update non-position non-geometry property */ diff --git a/visionforge-solid/src/jsMain/kotlin/hep/dataforge/vision/solid/three/ThreeProxyFactory.kt b/visionforge-solid/src/jsMain/kotlin/hep/dataforge/vision/solid/three/ThreeProxyFactory.kt index 2fd83dfa..9063a968 100644 --- a/visionforge-solid/src/jsMain/kotlin/hep/dataforge/vision/solid/three/ThreeProxyFactory.kt +++ b/visionforge-solid/src/jsMain/kotlin/hep/dataforge/vision/solid/three/ThreeProxyFactory.kt @@ -4,7 +4,6 @@ import hep.dataforge.names.toName import hep.dataforge.vision.solid.Proxy import hep.dataforge.vision.solid.Proxy.Companion.PROXY_CHILD_PROPERTY_PREFIX import hep.dataforge.vision.solid.Solid -import info.laht.threekt.core.BufferGeometry import info.laht.threekt.core.Object3D import info.laht.threekt.objects.Mesh import kotlin.reflect.KClass @@ -14,16 +13,16 @@ class ThreeProxyFactory(val three: ThreePlugin) : ThreeFactory { override val type: KClass = Proxy::class - private fun Object3D.replicate(): Object3D { - return when (this) { - is Mesh -> Mesh(geometry as BufferGeometry, material) - else -> clone(false) - }.also { obj: Object3D -> - children.forEach { child: Object3D -> - obj.add(child.replicate()) - } - } - } +// private fun Object3D.replicate(): Object3D { +// return when (this) { +// is Mesh -> Mesh(geometry as BufferGeometry, material) +// else -> clone(false) +// }.also { obj: Object3D -> +// children.forEach { child: Object3D -> +// obj.add(child.replicate()) +// } +// } +// } override fun invoke(obj: Proxy): Object3D { val template = obj.prototype @@ -31,10 +30,13 @@ class ThreeProxyFactory(val three: ThreePlugin) : ThreeFactory { three.buildObject3D(template) } - val object3D: Object3D = cachedObject.replicate() - + val object3D: Object3D = cachedObject.clone()//cachedObject.replicate() object3D.updatePosition(obj) + if(object3D is Mesh){ + object3D.applyProperties(obj) + } + obj.onPropertyChange(this) { name -> if (name.first()?.body == PROXY_CHILD_PROPERTY_PREFIX) { val childName = name.first()?.index?.toName() ?: error("Wrong syntax for proxy child property: '$name'") diff --git a/visionforge-solid/src/jsMain/kotlin/hep/dataforge/vision/solid/three/outputConfig.kt b/visionforge-solid/src/jsMain/kotlin/hep/dataforge/vision/solid/three/outputConfig.kt index fe01bba8..2956f8cc 100644 --- a/visionforge-solid/src/jsMain/kotlin/hep/dataforge/vision/solid/three/outputConfig.kt +++ b/visionforge-solid/src/jsMain/kotlin/hep/dataforge/vision/solid/three/outputConfig.kt @@ -1,6 +1,7 @@ package hep.dataforge.vision.solid.three import hep.dataforge.js.requireJS +import hep.dataforge.meta.DFExperimental import hep.dataforge.vision.bootstrap.accordion import hep.dataforge.vision.bootstrap.entry import hep.dataforge.vision.solid.SolidGroup @@ -31,6 +32,7 @@ private fun saveData(event: Event, fileName: String, mimeType: String = "text/pl fileSaver.saveAs(blob, fileName) } +@OptIn(DFExperimental::class) fun RBuilder.canvasControls(canvas: ThreeCanvas) = accordion("controls") { entry("Settings") { div("row") { diff --git a/visionforge-solid/src/jsMain/kotlin/info/laht/threekt/objects/Mesh.kt b/visionforge-solid/src/jsMain/kotlin/info/laht/threekt/objects/Mesh.kt index 6c5b4555..78dcb9f6 100644 --- a/visionforge-solid/src/jsMain/kotlin/info/laht/threekt/objects/Mesh.kt +++ b/visionforge-solid/src/jsMain/kotlin/info/laht/threekt/objects/Mesh.kt @@ -33,8 +33,8 @@ import info.laht.threekt.materials.Material open external class Mesh : Object3D { - constructor(geometry: Geometry, material: Material) - constructor(geometry: BufferGeometry, material: Material) + constructor(geometry: Geometry?, material: Material?) + constructor(geometry: BufferGeometry?, material: Material?) var geometry: dynamic var material: Material From 998afb1ce0c1b3a9b3f6bb75bc9351c3cd7c9bfc Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Wed, 26 Aug 2020 22:54:26 +0300 Subject: [PATCH 005/151] replicate mesh --- demo/gdml/build.gradle.kts | 1 + .../vision/gdml/demo/GDMLAppComponent.kt | 1 - .../dataforge/vision/gdml/GDMLTransformer.kt | 24 ++++++++++++++---- .../vision/solid/three/ThreeProxyFactory.kt | 25 +++++++++++-------- 4 files changed, 34 insertions(+), 17 deletions(-) diff --git a/demo/gdml/build.gradle.kts b/demo/gdml/build.gradle.kts index 8d5342c3..1ae0ffd9 100644 --- a/demo/gdml/build.gradle.kts +++ b/demo/gdml/build.gradle.kts @@ -1,5 +1,6 @@ import scientifik.DependencyConfiguration import scientifik.FXModule +import scientifik.useFx plugins { id("scientifik.mpp") diff --git a/demo/gdml/src/jsMain/kotlin/hep/dataforge/vision/gdml/demo/GDMLAppComponent.kt b/demo/gdml/src/jsMain/kotlin/hep/dataforge/vision/gdml/demo/GDMLAppComponent.kt index ae1dce60..99d4bc59 100644 --- a/demo/gdml/src/jsMain/kotlin/hep/dataforge/vision/gdml/demo/GDMLAppComponent.kt +++ b/demo/gdml/src/jsMain/kotlin/hep/dataforge/vision/gdml/demo/GDMLAppComponent.kt @@ -67,7 +67,6 @@ val GDMLApp = component { props -> error("File extension is not recognized: $name") } } - parsedVision.config["edges.enabled"] = false vision = parsedVision } diff --git a/visionforge-gdml/src/commonMain/kotlin/hep/dataforge/vision/gdml/GDMLTransformer.kt b/visionforge-gdml/src/commonMain/kotlin/hep/dataforge/vision/gdml/GDMLTransformer.kt index ad48480b..299a9b16 100644 --- a/visionforge-gdml/src/commonMain/kotlin/hep/dataforge/vision/gdml/GDMLTransformer.kt +++ b/visionforge-gdml/src/commonMain/kotlin/hep/dataforge/vision/gdml/GDMLTransformer.kt @@ -2,6 +2,7 @@ package hep.dataforge.vision.gdml import hep.dataforge.meta.Meta import hep.dataforge.meta.MetaBuilder +import hep.dataforge.meta.set import hep.dataforge.names.Name import hep.dataforge.names.asName import hep.dataforge.names.plus @@ -15,6 +16,9 @@ import kotlin.math.cos import kotlin.math.sin import kotlin.random.Random +private val solidsName = "solids".asName() +private val volumesName = "volumes".asName() + class GDMLTransformer(val root: GDML) { //private val materialCache = HashMap() private val random = Random(222) @@ -35,6 +39,18 @@ class GDMLTransformer(val root: GDML) { * A special group for local templates */ internal val proto by lazy { SolidGroup() } + + internal val solids by lazy { + proto.group(solidsName) { + config["edges.enabled"] = false + } + } + + internal val volumes by lazy { + proto.group(volumesName) { + config["edges.enabled"] = true + } + } private val styleCache = HashMap() var solidConfiguration: Solid.(parent: GDMLVolume, solid: GDMLSolid) -> Unit = { parent, _ -> @@ -231,7 +247,7 @@ private fun SolidGroup.addSolid( } -private val solidsName = "solids".asName() + private fun SolidGroup.addSolidWithCaching( context: GDMLTransformer, @@ -245,8 +261,7 @@ private fun SolidGroup.addSolidWithCaching( GDMLTransformer.Action.CACHE -> { val fullName = solidsName + solid.name.asName() if (context.proto[fullName] == null) { - val parent = (context.proto[solidsName] as? SolidGroup) ?: context.proto.group(solidsName) - parent.addSolid(context, solid, solid.name) + context.solids.addSolid(context, solid, solid.name) } ref(fullName, name) } @@ -257,7 +272,6 @@ private fun SolidGroup.addSolidWithCaching( } } -private val volumesName = "volumes".asName() private fun SolidGroup.addPhysicalVolume( context: GDMLTransformer, @@ -288,7 +302,7 @@ private fun SolidGroup.addPhysicalVolume( context.proto[fullName] = volume(context, volume) } - this[physVolume.name ?: ""] = Proxy(this, fullName).withPosition(context, physVolume) + ref(fullName,physVolume.name ?: "").withPosition(context, physVolume) } GDMLTransformer.Action.REJECT -> { //ignore diff --git a/visionforge-solid/src/jsMain/kotlin/hep/dataforge/vision/solid/three/ThreeProxyFactory.kt b/visionforge-solid/src/jsMain/kotlin/hep/dataforge/vision/solid/three/ThreeProxyFactory.kt index 9063a968..2ceb75aa 100644 --- a/visionforge-solid/src/jsMain/kotlin/hep/dataforge/vision/solid/three/ThreeProxyFactory.kt +++ b/visionforge-solid/src/jsMain/kotlin/hep/dataforge/vision/solid/three/ThreeProxyFactory.kt @@ -4,6 +4,7 @@ import hep.dataforge.names.toName import hep.dataforge.vision.solid.Proxy import hep.dataforge.vision.solid.Proxy.Companion.PROXY_CHILD_PROPERTY_PREFIX import hep.dataforge.vision.solid.Solid +import info.laht.threekt.core.BufferGeometry import info.laht.threekt.core.Object3D import info.laht.threekt.objects.Mesh import kotlin.reflect.KClass @@ -13,16 +14,18 @@ class ThreeProxyFactory(val three: ThreePlugin) : ThreeFactory { override val type: KClass = Proxy::class -// private fun Object3D.replicate(): Object3D { -// return when (this) { -// is Mesh -> Mesh(geometry as BufferGeometry, material) -// else -> clone(false) -// }.also { obj: Object3D -> -// children.forEach { child: Object3D -> -// obj.add(child.replicate()) -// } -// } -// } + private fun Object3D.replicate(): Object3D { + return when (this) { + is Mesh -> Mesh(geometry as BufferGeometry, material).also { + it.applyMatrix(matrix) + } + else -> clone(false) + }.also { obj: Object3D -> + children.forEach { child: Object3D -> + obj.add(child.replicate()) + } + } + } override fun invoke(obj: Proxy): Object3D { val template = obj.prototype @@ -30,7 +33,7 @@ class ThreeProxyFactory(val three: ThreePlugin) : ThreeFactory { three.buildObject3D(template) } - val object3D: Object3D = cachedObject.clone()//cachedObject.replicate() + val object3D: Object3D = cachedObject.replicate() object3D.updatePosition(obj) if(object3D is Mesh){ From ea82082304d46fb560b3cc529e376e0b2d26d7aa Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Wed, 26 Aug 2020 23:00:21 +0300 Subject: [PATCH 006/151] Add edges to transparent objects. remove unnecessary re-configuration --- .../vision/gdml/demo/GDMLAppComponent.kt | 2 +- .../vision/gdml/demo/GdmlJsDemoApp.kt | 14 +---------- .../dataforge/vision/gdml/demo/readFile.kt | 24 +++++++++---------- .../dataforge/vision/gdml/GDMLTransformer.kt | 5 ++-- 4 files changed, 16 insertions(+), 29 deletions(-) diff --git a/demo/gdml/src/jsMain/kotlin/hep/dataforge/vision/gdml/demo/GDMLAppComponent.kt b/demo/gdml/src/jsMain/kotlin/hep/dataforge/vision/gdml/demo/GDMLAppComponent.kt index 99d4bc59..9cd2c2bd 100644 --- a/demo/gdml/src/jsMain/kotlin/hep/dataforge/vision/gdml/demo/GDMLAppComponent.kt +++ b/demo/gdml/src/jsMain/kotlin/hep/dataforge/vision/gdml/demo/GDMLAppComponent.kt @@ -59,7 +59,7 @@ val GDMLApp = component { props -> val parsedVision = when { name.endsWith(".gdml") || name.endsWith(".xml") -> { val gdml = GDML.parse(data) - gdml.toVision(gdmlConfiguration) + gdml.toVision() } name.endsWith(".json") -> SolidGroup.parseJson(data) else -> { diff --git a/demo/gdml/src/jsMain/kotlin/hep/dataforge/vision/gdml/demo/GdmlJsDemoApp.kt b/demo/gdml/src/jsMain/kotlin/hep/dataforge/vision/gdml/demo/GdmlJsDemoApp.kt index 40d35a09..fc0478f0 100644 --- a/demo/gdml/src/jsMain/kotlin/hep/dataforge/vision/gdml/demo/GdmlJsDemoApp.kt +++ b/demo/gdml/src/jsMain/kotlin/hep/dataforge/vision/gdml/demo/GdmlJsDemoApp.kt @@ -14,18 +14,6 @@ import styled.injectGlobal import kotlin.browser.document -val gdmlConfiguration: GDMLTransformer.() -> Unit = { - lUnit = LUnit.CM - - solidConfiguration = { parent, _ -> - if (parent.physVolumes.isNotEmpty()) { - useStyle("opaque") { - MATERIAL_OPACITY_KEY put 0.3 - } - } - } -} - private class GDMLDemoApp : Application { override fun start(state: Map) { @@ -46,7 +34,7 @@ private class GDMLDemoApp : Application { child(GDMLApp) { attrs { this.context = context - this.rootObject = cubes().toVision(gdmlConfiguration) + this.rootObject = cubes().toVision() } } } diff --git a/demo/gdml/src/jvmMain/kotlin/hep/dataforge/vision/gdml/demo/readFile.kt b/demo/gdml/src/jvmMain/kotlin/hep/dataforge/vision/gdml/demo/readFile.kt index c0fcd2ed..355d6f98 100644 --- a/demo/gdml/src/jvmMain/kotlin/hep/dataforge/vision/gdml/demo/readFile.kt +++ b/demo/gdml/src/jvmMain/kotlin/hep/dataforge/vision/gdml/demo/readFile.kt @@ -18,18 +18,18 @@ import java.util.zip.ZipInputStream fun SolidManager.Companion.readFile(file: File): SolidGroup = when { file.extension == "gdml" || file.extension == "xml" -> { GDML.readFile(file.toPath()).toVision { - lUnit = LUnit.CM - - solidConfiguration = { parent, solid -> - if (solid.name == "cave") { - setItem(SolidMaterial.MATERIAL_WIREFRAME_KEY, true.asValue()) - } - if (parent.physVolumes.isNotEmpty()) { - useStyle("opaque") { - SolidMaterial.MATERIAL_OPACITY_KEY put 0.3 - } - } - } +// lUnit = LUnit.CM +// +// solidConfiguration = { parent, solid -> +// if (solid.name == "cave") { +// setItem(SolidMaterial.MATERIAL_WIREFRAME_KEY, true.asValue()) +// } +// if (parent.physVolumes.isNotEmpty()) { +// useStyle("opaque") { +// SolidMaterial.MATERIAL_OPACITY_KEY put 0.3 +// } +// } +// } } } file.extension == "json" -> SolidGroup.parseJson(file.readText()) diff --git a/visionforge-gdml/src/commonMain/kotlin/hep/dataforge/vision/gdml/GDMLTransformer.kt b/visionforge-gdml/src/commonMain/kotlin/hep/dataforge/vision/gdml/GDMLTransformer.kt index 299a9b16..df14eb40 100644 --- a/visionforge-gdml/src/commonMain/kotlin/hep/dataforge/vision/gdml/GDMLTransformer.kt +++ b/visionforge-gdml/src/commonMain/kotlin/hep/dataforge/vision/gdml/GDMLTransformer.kt @@ -47,9 +47,7 @@ class GDMLTransformer(val root: GDML) { } internal val volumes by lazy { - proto.group(volumesName) { - config["edges.enabled"] = true - } + proto.group(volumesName) } private val styleCache = HashMap() @@ -58,6 +56,7 @@ class GDMLTransformer(val root: GDML) { if (parent.physVolumes.isNotEmpty()) { useStyle("opaque") { SolidMaterial.MATERIAL_OPACITY_KEY put 0.3 + "edges.enabled" put true } } } From 68cf4748d8e8aca5b2110263617322ecc933803d Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Thu, 27 Aug 2020 11:10:28 +0300 Subject: [PATCH 007/151] Fix name replication --- .../dataforge/vision/gdml/GDMLTransformer.kt | 33 +++++++++++-------- .../vision/solid/three/ThreeProxyFactory.kt | 3 +- .../info/laht/threekt/core/BufferGeometry.kt | 2 +- .../kotlin/info/laht/threekt/core/Geometry.kt | 2 +- .../kotlin/info/laht/threekt/core/Object3D.kt | 2 +- 5 files changed, 24 insertions(+), 18 deletions(-) diff --git a/visionforge-gdml/src/commonMain/kotlin/hep/dataforge/vision/gdml/GDMLTransformer.kt b/visionforge-gdml/src/commonMain/kotlin/hep/dataforge/vision/gdml/GDMLTransformer.kt index df14eb40..94749b45 100644 --- a/visionforge-gdml/src/commonMain/kotlin/hep/dataforge/vision/gdml/GDMLTransformer.kt +++ b/visionforge-gdml/src/commonMain/kotlin/hep/dataforge/vision/gdml/GDMLTransformer.kt @@ -24,16 +24,16 @@ class GDMLTransformer(val root: GDML) { private val random = Random(222) enum class Action { - ACCEPT, + ADD, REJECT, - CACHE + PROTOTYPE } var lUnit: LUnit = LUnit.MM var aUnit: AUnit = AUnit.RADIAN - var solidAction: (GDMLSolid) -> Action = { Action.CACHE } - var volumeAction: (GDMLGroup) -> Action = { Action.CACHE } + var solidAction: (GDMLSolid) -> Action = { Action.PROTOTYPE } + var volumeAction: (GDMLGroup) -> Action = { Action.PROTOTYPE } /** * A special group for local templates @@ -49,6 +49,15 @@ class GDMLTransformer(val root: GDML) { internal val volumes by lazy { proto.group(volumesName) } + +// fun proxySolid(group: SolidGroup, solid: GDMLSolid, name: String): Proxy { +// val fullName = solidsName + name +// if (proto[fullName] == null) { +// solids.addSolid(this, solid, name) +// } +// return group.ref(fullName, name) +// } + private val styleCache = HashMap() var solidConfiguration: Solid.(parent: GDMLVolume, solid: GDMLSolid) -> Unit = { parent, _ -> @@ -245,19 +254,17 @@ private fun SolidGroup.addSolid( } } - - - private fun SolidGroup.addSolidWithCaching( context: GDMLTransformer, solid: GDMLSolid, name: String = solid.name ): Solid? { return when (context.solidAction(solid)) { - GDMLTransformer.Action.ACCEPT -> { + GDMLTransformer.Action.ADD -> { addSolid(context, solid, name) } - GDMLTransformer.Action.CACHE -> { + GDMLTransformer.Action.PROTOTYPE -> { +// context.proxySolid(this, solid, name) val fullName = solidsName + solid.name.asName() if (context.proto[fullName] == null) { context.solids.addSolid(context, solid, solid.name) @@ -271,7 +278,6 @@ private fun SolidGroup.addSolidWithCaching( } } - private fun SolidGroup.addPhysicalVolume( context: GDMLTransformer, physVolume: GDMLPhysVolume @@ -291,17 +297,16 @@ private fun SolidGroup.addPhysicalVolume( } when (context.volumeAction(volume)) { - GDMLTransformer.Action.ACCEPT -> { + GDMLTransformer.Action.ADD -> { val group: SolidGroup = volume(context, volume) this[physVolume.name ?: ""] = group.withPosition(context, physVolume) } - GDMLTransformer.Action.CACHE -> { + GDMLTransformer.Action.PROTOTYPE -> { val fullName = volumesName + volume.name.asName() if (context.proto[fullName] == null) { context.proto[fullName] = volume(context, volume) } - - ref(fullName,physVolume.name ?: "").withPosition(context, physVolume) + ref(fullName, physVolume.name ?: "").withPosition(context, physVolume) } GDMLTransformer.Action.REJECT -> { //ignore diff --git a/visionforge-solid/src/jsMain/kotlin/hep/dataforge/vision/solid/three/ThreeProxyFactory.kt b/visionforge-solid/src/jsMain/kotlin/hep/dataforge/vision/solid/three/ThreeProxyFactory.kt index 2ceb75aa..832dd32d 100644 --- a/visionforge-solid/src/jsMain/kotlin/hep/dataforge/vision/solid/three/ThreeProxyFactory.kt +++ b/visionforge-solid/src/jsMain/kotlin/hep/dataforge/vision/solid/three/ThreeProxyFactory.kt @@ -17,10 +17,11 @@ class ThreeProxyFactory(val three: ThreePlugin) : ThreeFactory { private fun Object3D.replicate(): Object3D { return when (this) { is Mesh -> Mesh(geometry as BufferGeometry, material).also { - it.applyMatrix(matrix) + it.applyMatrix4(matrix) } else -> clone(false) }.also { obj: Object3D -> + obj.name = this.name children.forEach { child: Object3D -> obj.add(child.replicate()) } diff --git a/visionforge-solid/src/jsMain/kotlin/info/laht/threekt/core/BufferGeometry.kt b/visionforge-solid/src/jsMain/kotlin/info/laht/threekt/core/BufferGeometry.kt index a4219aeb..c3fd093b 100644 --- a/visionforge-solid/src/jsMain/kotlin/info/laht/threekt/core/BufferGeometry.kt +++ b/visionforge-solid/src/jsMain/kotlin/info/laht/threekt/core/BufferGeometry.kt @@ -99,7 +99,7 @@ open external class BufferGeometry { fun merge(bufferGeometry: BufferGeometry, offset: Int = definedExternally): BufferGeometry - fun applyMatrix(matrix: Matrix4) + fun applyMatrix4(matrix: Matrix4) fun lookAt(vector: Vector3): BufferGeometry fun rotateX(radians: Double): BufferGeometry fun rotateY(radians: Double): BufferGeometry diff --git a/visionforge-solid/src/jsMain/kotlin/info/laht/threekt/core/Geometry.kt b/visionforge-solid/src/jsMain/kotlin/info/laht/threekt/core/Geometry.kt index 518cc6d6..522ab07c 100644 --- a/visionforge-solid/src/jsMain/kotlin/info/laht/threekt/core/Geometry.kt +++ b/visionforge-solid/src/jsMain/kotlin/info/laht/threekt/core/Geometry.kt @@ -70,7 +70,7 @@ open external class Geometry { var lineDistancesNeedUpdate: Boolean var groupsNeedUpdate: Boolean - fun applyMatrix(matrix: Matrix4): Geometry + fun applyMatrix4(matrix: Matrix4): Geometry fun rotateX(angle: Number): Geometry fun rotateY(angle: Number): Geometry fun rotateZ(angle: Number): Geometry diff --git a/visionforge-solid/src/jsMain/kotlin/info/laht/threekt/core/Object3D.kt b/visionforge-solid/src/jsMain/kotlin/info/laht/threekt/core/Object3D.kt index be7a95d5..e49add5e 100644 --- a/visionforge-solid/src/jsMain/kotlin/info/laht/threekt/core/Object3D.kt +++ b/visionforge-solid/src/jsMain/kotlin/info/laht/threekt/core/Object3D.kt @@ -165,7 +165,7 @@ open external class Object3D { /** * Applies the matrix transform to the object and updates the object's position, rotation and scale. */ - fun applyMatrix(matrix: Matrix4) + fun applyMatrix4(matrix: Matrix4) /** * Applies the rotation represented by the quaternion to the object. From c83a25b0a1dcc61a25f3d06c68ae9c526a216033 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Thu, 27 Aug 2020 14:29:50 +0300 Subject: [PATCH 008/151] GDML converter refactoring --- .../dataforge/vision/gdml/GDMLTransformer.kt | 516 +++++++++--------- .../dataforge/vision/gdml/GdmlOptimizer.kt | 134 ++--- 2 files changed, 332 insertions(+), 318 deletions(-) diff --git a/visionforge-gdml/src/commonMain/kotlin/hep/dataforge/vision/gdml/GDMLTransformer.kt b/visionforge-gdml/src/commonMain/kotlin/hep/dataforge/vision/gdml/GDMLTransformer.kt index 94749b45..ceecd768 100644 --- a/visionforge-gdml/src/commonMain/kotlin/hep/dataforge/vision/gdml/GDMLTransformer.kt +++ b/visionforge-gdml/src/commonMain/kotlin/hep/dataforge/vision/gdml/GDMLTransformer.kt @@ -7,6 +7,7 @@ import hep.dataforge.names.Name import hep.dataforge.names.asName import hep.dataforge.names.plus import hep.dataforge.names.toName +import hep.dataforge.vision.MutableVisionGroup import hep.dataforge.vision.set import hep.dataforge.vision.solid.* import hep.dataforge.vision.solid.SolidMaterial.Companion.MATERIAL_COLOR_KEY @@ -19,7 +20,7 @@ import kotlin.random.Random private val solidsName = "solids".asName() private val volumesName = "volumes".asName() -class GDMLTransformer(val root: GDML) { +class GDMLTransformer internal constructor(val root: GDML) { //private val materialCache = HashMap() private val random = Random(222) @@ -38,25 +39,35 @@ class GDMLTransformer(val root: GDML) { /** * A special group for local templates */ - internal val proto by lazy { SolidGroup() } + private val proto by lazy { SolidGroup() } - internal val solids by lazy { + private val solids by lazy { proto.group(solidsName) { config["edges.enabled"] = false } } - internal val volumes by lazy { - proto.group(volumesName) + private val referenceStore = HashMap>() + + private fun proxySolid(group: SolidGroup, solid: GDMLSolid, name: String): Proxy { + val templateName = solidsName + name + if (proto[templateName] == null) { + solids.addSolid(solid, name) + } + val ref = group.ref(templateName, name) + referenceStore.getOrPut(templateName) { ArrayList() }.add(ref) + return ref } -// fun proxySolid(group: SolidGroup, solid: GDMLSolid, name: String): Proxy { -// val fullName = solidsName + name -// if (proto[fullName] == null) { -// solids.addSolid(this, solid, name) -// } -// return group.ref(fullName, name) -// } + private fun proxyVolume(group: SolidGroup, physVolume: GDMLPhysVolume, volume: GDMLGroup): Proxy { + val templateName = volumesName + volume.name.asName() + if (proto[templateName] == null) { + proto[templateName] = volume(volume) + } + val ref = group.ref(templateName, physVolume.name ?: "").withPosition(physVolume) + referenceStore.getOrPut(templateName) { ArrayList() }.add(ref) + return ref + } private val styleCache = HashMap() @@ -70,14 +81,14 @@ class GDMLTransformer(val root: GDML) { } } - fun Solid.useStyle(name: String, builder: MetaBuilder.() -> Unit) { + private fun Solid.useStyle(name: String, builder: MetaBuilder.() -> Unit) { styleCache.getOrPut(name.toName()) { Meta(builder) } useStyle(name) } - internal fun configureSolid(obj: Solid, parent: GDMLVolume, solid: GDMLSolid) { + private fun configureSolid(obj: Solid, parent: GDMLVolume, solid: GDMLSolid) { val material = parent.materialref.resolve(root) ?: GDMLElement(parent.materialref.ref) val styleName = "material[${material.name}]" @@ -92,8 +103,244 @@ class GDMLTransformer(val root: GDML) { var onFinish: GDMLTransformer.() -> Unit = {} - internal fun finalize(final: SolidGroup): SolidGroup { + + private fun T.withPosition( + newPos: GDMLPosition? = null, + newRotation: GDMLRotation? = null, + newScale: GDMLScale? = null + ): T = apply { + newPos?.let { + val point = Point3D(it.x(lUnit), it.y(lUnit), it.z(lUnit)) + if (position != null || point != World.ZERO) { + position = point + } + } + newRotation?.let { + val point = Point3D(it.x(aUnit), it.y(aUnit), it.z(aUnit)) + if (rotation != null || point != World.ZERO) { + rotation = point + } + //this@withPosition.rotationOrder = RotationOrder.ZXY + } + newScale?.let { + val point = Point3D(it.x, it.y, it.z) + if (scale != null || point != World.ONE) { + scale = point + } + } + //TODO convert units if needed + } + + private fun T.withPosition(physVolume: GDMLPhysVolume): T = withPosition( + physVolume.resolvePosition(root), + physVolume.resolveRotation(root), + physVolume.resolveScale(root) + ) + + @Suppress("NOTHING_TO_INLINE") + private inline operator fun Number.times(d: Double) = toDouble() * d + + @Suppress("NOTHING_TO_INLINE") + private inline operator fun Number.times(f: Float) = toFloat() * f + + private fun SolidGroup.addSolid( + solid: GDMLSolid, + name: String = "" + ): Solid { + //context.solidAdded(solid) + val lScale = solid.lscale(lUnit) + val aScale = solid.ascale() + return when (solid) { + is GDMLBox -> box(solid.x * lScale, solid.y * lScale, solid.z * lScale, name) + is GDMLTube -> tube( + solid.rmax * lScale, + solid.z * lScale, + solid.rmin * lScale, + solid.startphi * aScale, + solid.deltaphi * aScale, + name + ) + is GDMLCone -> cone(solid.rmax1, solid.z, solid.rmax2, name = name) { + require(solid.rmin1 == 0.0) { "Empty cones are not supported" } + require(solid.rmin2 == 0.0) { "Empty cones are not supported" } + startAngle = solid.startphi.toFloat() + angle = solid.deltaphi.toFloat() + } + is GDMLXtru -> extrude(name) { + shape { + solid.vertices.forEach { + point(it.x * lScale, it.y * lScale) + } + } + solid.sections.sortedBy { it.zOrder }.forEach { section -> + layer( + section.zPosition * lScale, + section.xOffset * lScale, + section.yOffset * lScale, + section.scalingFactor + ) + } + } + is GDMLScaledSolid -> { + //Add solid with modified scale + val innerSolid: GDMLSolid = solid.solidref.resolve(root) + ?: error("Solid with tag ${solid.solidref.ref} for scaled solid ${solid.name} not defined") + + addSolid(innerSolid, name).apply { + scaleX *= solid.scale.x.toFloat() + scaleY *= solid.scale.y.toFloat() + scaleZ = solid.scale.z.toFloat() + } + } + is GDMLSphere -> sphere(solid.rmax * lScale, solid.deltaphi * aScale, solid.deltatheta * aScale, name) { + phiStart = solid.startphi * aScale + thetaStart = solid.starttheta * aScale + } + is GDMLOrb -> sphere(solid.r * lScale, name = name) + is GDMLPolyhedra -> extrude(name) { + //getting the radius of first + require(solid.planes.size > 1) { "The polyhedron geometry requires at least two planes" } + val baseRadius = solid.planes.first().rmax * lScale + shape { + (0..solid.numsides).forEach { + val phi = solid.deltaphi * aScale / solid.numsides * it + solid.startphi * aScale + (baseRadius * cos(phi) to baseRadius * sin(phi)) + } + } + solid.planes.forEach { plane -> + //scaling all radii relative to first layer radius + layer(plane.z * lScale, scale = plane.rmax * lScale / baseRadius) + } + } + is GDMLBoolSolid -> { + val first: GDMLSolid = solid.first.resolve(root) ?: error("") + val second: GDMLSolid = solid.second.resolve(root) ?: error("") + val type: CompositeType = when (solid) { + is GDMLUnion -> CompositeType.UNION + is GDMLSubtraction -> CompositeType.SUBTRACT + is GDMLIntersection -> CompositeType.INTERSECT + } + + return composite(type, name) { + addSolid(first).withPosition( + solid.resolveFirstPosition(root), + solid.resolveFirstRotation(root), + null + ) + + addSolid(second).withPosition( + solid.resolvePosition(root), + solid.resolveRotation(root), + null + ) + + } + } + else -> error("Renderer for $solid not supported yet") + } + } + + private fun SolidGroup.addSolidWithCaching( + solid: GDMLSolid, + name: String = solid.name + ): Solid? { + return when (solidAction(solid)) { + Action.ADD -> { + addSolid(solid, name) + } + Action.PROTOTYPE -> { + proxySolid(this, solid, name) + } + Action.REJECT -> { + //ignore + null + } + } + } + + private fun SolidGroup.addPhysicalVolume( + physVolume: GDMLPhysVolume + ) { + val volume: GDMLGroup = physVolume.volumeref.resolve(root) + ?: error("Volume with ref ${physVolume.volumeref.ref} could not be resolved") + + // a special case for single solid volume + if (volume is GDMLVolume && volume.physVolumes.isEmpty() && volume.placement == null) { + val solid = volume.solidref.resolve(root) + ?: error("Solid with tag ${volume.solidref.ref} for volume ${volume.name} not defined") + addSolidWithCaching(solid, physVolume.name ?: "")?.apply { + configureSolid(this, volume, solid) + withPosition(physVolume) + } + return + } + + when (volumeAction(volume)) { + Action.ADD -> { + val group: SolidGroup = volume(volume) + this[physVolume.name ?: ""] = group.withPosition(physVolume) + } + Action.PROTOTYPE -> { + proxyVolume(this, physVolume, volume) + } + Action.REJECT -> { + //ignore + } + } + } + + private fun SolidGroup.addDivisionVolume( + divisionVolume: GDMLDivisionVolume + ) { + val volume: GDMLGroup = divisionVolume.volumeref.resolve(root) + ?: error("Volume with ref ${divisionVolume.volumeref.ref} could not be resolved") + + //TODO add divisions + set(Name.EMPTY, volume(volume)) + } + + private fun volume( + group: GDMLGroup + ): SolidGroup = SolidGroup().apply { + if (group is GDMLVolume) { + val solid: GDMLSolid = group.solidref.resolve(root) + ?: error("Solid with tag ${group.solidref.ref} for volume ${group.name} not defined") + + addSolidWithCaching(solid)?.apply { + configureSolid(this, group, solid) + } + + when (val vol: GDMLPlacement? = group.placement) { + is GDMLPhysVolume -> addPhysicalVolume(vol) + is GDMLDivisionVolume -> addDivisionVolume(vol) + } + } + + group.physVolumes.forEach { physVolume -> + addPhysicalVolume(physVolume) + } + } + + private fun finalize(final: SolidGroup): SolidGroup { //final.prototypes = proto + final.useStyle("GDML") { + Solid.ROTATION_ORDER_KEY put RotationOrder.ZXY + } + + //inline prototypes +// referenceStore.forEach { (protoName, list) -> +// val proxy = list.singleOrNull() ?: return@forEach +// val parent = proxy.parent as? MutableVisionGroup ?: return@forEach +// val token = parent.children.entries.find { it.value == proxy }?.key ?: error("Inconsistent reference cache") +// val prototype = proto[protoName] as? Solid ?: error("Inconsistent reference cache") +// prototype.parent = null +// parent[token] = prototype +// prototype.updateFrom(proxy) +// +// //FIXME update prototype +// proto[protoName] = null +// } + final.prototypes { proto.children.forEach { (token, item) -> item.parent = null @@ -105,252 +352,19 @@ class GDMLTransformer(val root: GDML) { define(it.key.toString(), it.value) } } - final.rotationOrder = RotationOrder.ZXY onFinish(this@GDMLTransformer) return final } -} - -private fun Solid.withPosition( - lUnit: LUnit, - aUnit: AUnit = AUnit.RADIAN, - newPos: GDMLPosition? = null, - newRotation: GDMLRotation? = null, - newScale: GDMLScale? = null -): Solid = apply { - newPos?.let { - val point = Point3D(it.x(lUnit), it.y(lUnit), it.z(lUnit)) - if (position != null || point != World.ZERO) { - position = point - } - } - newRotation?.let { - val point = Point3D(it.x(aUnit), it.y(aUnit), it.z(aUnit)) - if (rotation != null || point != World.ZERO) { - rotation = point - } - //this@withPosition.rotationOrder = RotationOrder.ZXY - } - newScale?.let { - val point = Point3D(it.x, it.y, it.z) - if (scale != null || point != World.ONE) { - scale = point - } - } - //TODO convert units if needed -} - -private fun Solid.withPosition(context: GDMLTransformer, physVolume: GDMLPhysVolume) = withPosition( - context.lUnit, context.aUnit, - physVolume.resolvePosition(context.root), - physVolume.resolveRotation(context.root), - physVolume.resolveScale(context.root) -) - -@Suppress("NOTHING_TO_INLINE") -private inline operator fun Number.times(d: Double) = toDouble() * d - -@Suppress("NOTHING_TO_INLINE") -private inline operator fun Number.times(f: Float) = toFloat() * f - -private fun SolidGroup.addSolid( - context: GDMLTransformer, - solid: GDMLSolid, - name: String = "" -): Solid { - //context.solidAdded(solid) - val lScale = solid.lscale(context.lUnit) - val aScale = solid.ascale() - return when (solid) { - is GDMLBox -> box(solid.x * lScale, solid.y * lScale, solid.z * lScale, name) - is GDMLTube -> tube( - solid.rmax * lScale, - solid.z * lScale, - solid.rmin * lScale, - solid.startphi * aScale, - solid.deltaphi * aScale, - name - ) - is GDMLCone -> cone(solid.rmax1, solid.z, solid.rmax2, name = name) { - require(solid.rmin1 == 0.0) { "Empty cones are not supported" } - require(solid.rmin2 == 0.0) { "Empty cones are not supported" } - startAngle = solid.startphi.toFloat() - angle = solid.deltaphi.toFloat() - } - is GDMLXtru -> extrude(name) { - shape { - solid.vertices.forEach { - point(it.x * lScale, it.y * lScale) - } - } - solid.sections.sortedBy { it.zOrder }.forEach { section -> - layer( - section.zPosition * lScale, - section.xOffset * lScale, - section.yOffset * lScale, - section.scalingFactor - ) - } - } - is GDMLScaledSolid -> { - //Add solid with modified scale - val innerSolid: GDMLSolid = solid.solidref.resolve(context.root) - ?: error("Solid with tag ${solid.solidref.ref} for scaled solid ${solid.name} not defined") - - addSolid(context, innerSolid, name).apply { - scaleX *= solid.scale.x.toFloat() - scaleY *= solid.scale.y.toFloat() - scaleZ = solid.scale.z.toFloat() - } - } - is GDMLSphere -> sphere(solid.rmax * lScale, solid.deltaphi * aScale, solid.deltatheta * aScale, name) { - phiStart = solid.startphi * aScale - thetaStart = solid.starttheta * aScale - } - is GDMLOrb -> sphere(solid.r * lScale, name = name) - is GDMLPolyhedra -> extrude(name) { - //getting the radius of first - require(solid.planes.size > 1) { "The polyhedron geometry requires at least two planes" } - val baseRadius = solid.planes.first().rmax * lScale - shape { - (0..solid.numsides).forEach { - val phi = solid.deltaphi * aScale / solid.numsides * it + solid.startphi * aScale - (baseRadius * cos(phi) to baseRadius * sin(phi)) - } - } - solid.planes.forEach { plane -> - //scaling all radii relative to first layer radius - layer(plane.z * lScale, scale = plane.rmax * lScale / baseRadius) - } - } - is GDMLBoolSolid -> { - val first: GDMLSolid = solid.first.resolve(context.root) ?: error("") - val second: GDMLSolid = solid.second.resolve(context.root) ?: error("") - val type: CompositeType = when (solid) { - is GDMLUnion -> CompositeType.UNION - is GDMLSubtraction -> CompositeType.SUBTRACT - is GDMLIntersection -> CompositeType.INTERSECT - } - - return composite(type, name) { - addSolid(context, first).withPosition( - context.lUnit, context.aUnit, - solid.resolveFirstPosition(context.root), - solid.resolveFirstRotation(context.root), - null - ) - - addSolid(context, second).withPosition( - context.lUnit, context.aUnit, - solid.resolvePosition(context.root), - solid.resolveRotation(context.root), - null - ) - - } - } - else -> error("Renderer for $solid not supported yet") + val result by lazy { + finalize(volume(root.world)) } } -private fun SolidGroup.addSolidWithCaching( - context: GDMLTransformer, - solid: GDMLSolid, - name: String = solid.name -): Solid? { - return when (context.solidAction(solid)) { - GDMLTransformer.Action.ADD -> { - addSolid(context, solid, name) - } - GDMLTransformer.Action.PROTOTYPE -> { -// context.proxySolid(this, solid, name) - val fullName = solidsName + solid.name.asName() - if (context.proto[fullName] == null) { - context.solids.addSolid(context, solid, solid.name) - } - ref(fullName, name) - } - GDMLTransformer.Action.REJECT -> { - //ignore - null - } - } -} - -private fun SolidGroup.addPhysicalVolume( - context: GDMLTransformer, - physVolume: GDMLPhysVolume -) { - val volume: GDMLGroup = physVolume.volumeref.resolve(context.root) - ?: error("Volume with ref ${physVolume.volumeref.ref} could not be resolved") - - // a special case for single solid volume - if (volume is GDMLVolume && volume.physVolumes.isEmpty() && volume.placement == null) { - val solid = volume.solidref.resolve(context.root) - ?: error("Solid with tag ${volume.solidref.ref} for volume ${volume.name} not defined") - addSolidWithCaching(context, solid, physVolume.name ?: "")?.apply { - context.configureSolid(this, volume, solid) - withPosition(context, physVolume) - } - return - } - - when (context.volumeAction(volume)) { - GDMLTransformer.Action.ADD -> { - val group: SolidGroup = volume(context, volume) - this[physVolume.name ?: ""] = group.withPosition(context, physVolume) - } - GDMLTransformer.Action.PROTOTYPE -> { - val fullName = volumesName + volume.name.asName() - if (context.proto[fullName] == null) { - context.proto[fullName] = volume(context, volume) - } - ref(fullName, physVolume.name ?: "").withPosition(context, physVolume) - } - GDMLTransformer.Action.REJECT -> { - //ignore - } - } -} - -private fun SolidGroup.addDivisionVolume( - context: GDMLTransformer, - divisionVolume: GDMLDivisionVolume -) { - val volume: GDMLGroup = divisionVolume.volumeref.resolve(context.root) - ?: error("Volume with ref ${divisionVolume.volumeref.ref} could not be resolved") - - //TODO add divisions - set(Name.EMPTY, volume(context, volume)) -} - -private fun volume( - context: GDMLTransformer, - group: GDMLGroup -): SolidGroup = SolidGroup().apply { - if (group is GDMLVolume) { - val solid: GDMLSolid = group.solidref.resolve(context.root) - ?: error("Solid with tag ${group.solidref.ref} for volume ${group.name} not defined") - - addSolidWithCaching(context, solid)?.apply { - context.configureSolid(this, group, solid) - } - - when (val vol: GDMLPlacement? = group.placement) { - is GDMLPhysVolume -> addPhysicalVolume(context, vol) - is GDMLDivisionVolume -> addDivisionVolume(context, vol) - } - } - - group.physVolumes.forEach { physVolume -> - addPhysicalVolume(context, physVolume) - } -} fun GDML.toVision(block: GDMLTransformer.() -> Unit = {}): SolidGroup { val context = GDMLTransformer(this).apply(block) - return context.finalize(volume(context, world)) + return context.result } /** diff --git a/visionforge-gdml/src/commonMain/kotlin/hep/dataforge/vision/gdml/GdmlOptimizer.kt b/visionforge-gdml/src/commonMain/kotlin/hep/dataforge/vision/gdml/GdmlOptimizer.kt index c138fcc6..dba7e32f 100644 --- a/visionforge-gdml/src/commonMain/kotlin/hep/dataforge/vision/gdml/GdmlOptimizer.kt +++ b/visionforge-gdml/src/commonMain/kotlin/hep/dataforge/vision/gdml/GdmlOptimizer.kt @@ -18,72 +18,72 @@ expect class Counter() { fun incrementAndGet(): Int } -@DFExperimental -private class GdmlOptimizer() : VisionVisitor { - val logger = KotlinLogging.logger("SingleChildReducer") - - private operator fun Point3D?.plus(other: Point3D?): Point3D? = if (this == null && other == null) { - null - } else { - (this ?: Point3D(0, 0, 0)) + (other ?: Point3D(0, 0, 0)) - } - - private fun Vision.updateFrom(other: Vision): Vision { - if (this is Solid && other is Solid) { - position += other.position - rotation += other.rotation - if (this.scale != null || other.scale != null) { - scaleX = scaleX.toDouble() * other.scaleX.toDouble() - scaleY = scaleY.toDouble() * other.scaleY.toDouble() - scaleZ = scaleZ.toDouble() * other.scaleZ.toDouble() - } - other.properties?.sequence()?.forEach { (name, item) -> - if (properties?.getItem(name) == null) { - config[name] = item - } - } - } - return this - } - - private val depthCount = HashMap() - - override suspend fun visit(name: Name, vision: Vision) { - val depth = name.length - depthCount.getOrPut(depth) { Counter() }.incrementAndGet() - } - - override fun skip(name: Name, vision: Vision): Boolean = vision is Proxy.ProxyChild - - override suspend fun visitChildren(name: Name, group: VisionGroup) { - if (name == "volumes".toName()) return - if (group !is MutableVisionGroup) return - - val newChildren = group.children.entries.associate { (visionToken, vision) -> - //Reduce single child groups - if (vision is VisionGroup && vision !is Proxy && vision.children.size == 1) { - val (token, child) = vision.children.entries.first() - child.parent = null - if (token != visionToken) { - child.config["solidName"] = token.toString() - } - visionToken to child.updateFrom(vision) - } else { - visionToken to vision - } - } - if (newChildren != group.children) { - group.removeAll() - newChildren.forEach { (token, child) -> - group[token] = child - } - } - } +private fun Point3D?.safePlus(other: Point3D?): Point3D? = if (this == null && other == null) { + null +} else { + (this ?: Point3D(0, 0, 0)) + (other ?: Point3D(0, 0, 0)) } -@DFExperimental -suspend fun SolidGroup.optimizeGdml(): Job = coroutineScope { - prototypes?.let { - VisionVisitor.visitTree(GdmlOptimizer(), this, it) - } ?: CompletableDeferred(Unit) -} \ No newline at end of file +internal fun Vision.updateFrom(other: Vision): Vision { + if (this is Solid && other is Solid) { + position = position.safePlus(other.position) + rotation = rotation.safePlus(other.rotation) + if (this.scale != null || other.scale != null) { + scaleX = scaleX.toDouble() * other.scaleX.toDouble() + scaleY = scaleY.toDouble() * other.scaleY.toDouble() + scaleZ = scaleZ.toDouble() * other.scaleZ.toDouble() + } + other.properties?.sequence()?.forEach { (name, item) -> + if (properties?.getItem(name) == null) { + config[name] = item + } + } + } + return this +} +// +//@DFExperimental +//private class GdmlOptimizer() : VisionVisitor { +// val logger = KotlinLogging.logger("SingleChildReducer") +// +// private val depthCount = HashMap() +// +// override suspend fun visit(name: Name, vision: Vision) { +// val depth = name.length +// depthCount.getOrPut(depth) { Counter() }.incrementAndGet() +// } +// +// override fun skip(name: Name, vision: Vision): Boolean = vision is Proxy.ProxyChild +// +// override suspend fun visitChildren(name: Name, group: VisionGroup) { +// if (name == "volumes".toName()) return +// if (group !is MutableVisionGroup) return +// +// val newChildren = group.children.entries.associate { (visionToken, vision) -> +// //Reduce single child groups +// if (vision is VisionGroup && vision !is Proxy && vision.children.size == 1) { +// val (token, child) = vision.children.entries.first() +// child.parent = null +// if (token != visionToken) { +// child.config["solidName"] = token.toString() +// } +// visionToken to child.updateFrom(vision) +// } else { +// visionToken to vision +// } +// } +// if (newChildren != group.children) { +// group.removeAll() +// newChildren.forEach { (token, child) -> +// group[token] = child +// } +// } +// } +//} +// +//@DFExperimental +//suspend fun SolidGroup.optimizeGdml(): Job = coroutineScope { +// prototypes?.let { +// VisionVisitor.visitTree(GdmlOptimizer(), this, it) +// } ?: CompletableDeferred(Unit) +//} \ No newline at end of file From 936114519755927c67b309a543781b97be6546be Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Thu, 27 Aug 2020 17:06:33 +0300 Subject: [PATCH 009/151] Fix dead test --- .../dataforge/vision/gdml/bmanStatistics.kt | 22 ++++++++++++------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/visionforge-gdml/src/jvmTest/kotlin/hep/dataforge/vision/gdml/bmanStatistics.kt b/visionforge-gdml/src/jvmTest/kotlin/hep/dataforge/vision/gdml/bmanStatistics.kt index a8af85c6..d737d2ae 100644 --- a/visionforge-gdml/src/jvmTest/kotlin/hep/dataforge/vision/gdml/bmanStatistics.kt +++ b/visionforge-gdml/src/jvmTest/kotlin/hep/dataforge/vision/gdml/bmanStatistics.kt @@ -1,5 +1,8 @@ package hep.dataforge.vision.gdml +import hep.dataforge.vision.solid.AbstractProxy +import hep.dataforge.vision.solid.prototype +import hep.dataforge.vision.visitor.countDistinct import hep.dataforge.vision.visitor.countDistinctBy import hep.dataforge.vision.visitor.flowStatistics import kotlinx.coroutines.Dispatchers @@ -7,6 +10,7 @@ import kotlinx.coroutines.withContext import nl.adaptivity.xmlutil.StAXReader import scientifik.gdml.GDML import java.io.File +import kotlin.reflect.KClass suspend fun main() { withContext(Dispatchers.Default) { @@ -19,16 +23,18 @@ suspend fun main() { val vision = xml.toVision() - vision.flowStatistics().countDistinctBy { it.type }.forEach { (depth, size) -> + vision.flowStatistics>{ _, child -> + child.prototype::class + }.countDistinct().forEach { (depth, size) -> println("$depth\t$size") } - println("***REDUCED***") - - vision.optimizeGdml() - - vision.flowStatistics().countDistinctBy { it.type }.forEach { (depth, size) -> - println("$depth\t$size") - } +// println("***REDUCED***") +// +// vision.optimizeGdml() +// +// vision.flowStatistics().countDistinctBy { it.type }.forEach { (depth, size) -> +// println("$depth\t$size") +// } } } \ No newline at end of file From 61165230916d9515b1eb5ed324d41ed28e69e381 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Fri, 2 Oct 2020 19:09:25 +0300 Subject: [PATCH 010/151] Major build update and refactoring --- .gitignore | 2 - CHANGELOG.md | 14 + build.gradle.kts | 31 +- demo/build.gradle.kts | 0 demo/gdml/build.gradle.kts | 23 +- .../hep/dataforge/vision/gdml/demo/cubes.kt | 2 +- .../vision/gdml/demo/GDMLAppComponent.kt | 11 +- .../vision/gdml/demo/GdmlJsDemoApp.kt | 5 +- demo/gdml/src/jsMain/resources/index.html | 2 +- .../dataforge/vision/gdml/demo/readFile.kt | 9 +- .../dataforge/vision/gdml/demo/saveToJson.kt | 8 +- .../vision/solid/FileSerializationTest.kt | 2 +- demo/muon-monitor/build.gradle.kts | 53 +-- .../mipt/npm/muon/monitor/MMAppComponent.kt | 1 + .../ru/mipt/npm/muon/monitor/MMDemoApp.kt | 8 +- .../src/jsMain/resources/index.html | 2 +- .../mipt/npm/muon/monitor/server/MMServer.kt | 4 +- demo/spatial-showcase/build.gradle.kts | 19 +- .../hep/dataforge/vision/solid/demo/demo.kt | 1 + .../src/jsMain/resources/index.html | 2 +- gradle.properties | 9 + gradle/wrapper/gradle-wrapper.properties | 2 +- playground/build.gradle.kts | 4 +- settings.gradle.kts | 32 +- ui/bootstrap/build.gradle.kts | 8 +- .../dataforge/vision/bootstrap/bootstrap.kt | 39 +- ui/material/build.gradle.kts | 12 +- ui/react/build.gradle.kts | 10 +- .../dataforge/vision/react/ConfigEditor.kt | 3 +- .../hep/dataforge/vision/react/MetaViewer.kt | 3 +- .../hep/dataforge/vision/react/ObjectTree.kt | 3 +- ui/ring/build.gradle.kts | 11 +- visionforge-core/build.gradle.kts | 11 +- .../dataforge/properties/ConfigProperty.kt | 2 +- .../hep/dataforge/vision/AbstractVision.kt | 6 +- .../dataforge/vision/AbstractVisionGroup.kt | 13 +- .../kotlin/hep/dataforge/vision/StyleSheet.kt | 28 +- .../kotlin/hep/dataforge/vision/Vision.kt | 43 +- .../hep/dataforge/vision/VisionGroup.kt | 50 ++- .../hep/dataforge/vision/VisionManager.kt | 87 ++-- .../hep/dataforge/vision/valueWidget.kt | 20 +- .../vision/visitor/StatisticsVisitor.kt | 1 + .../hep/dataforge/vision/editor/FXMeta.kt | 17 +- visionforge-gdml/build.gradle.kts | 4 +- .../dataforge/vision/gdml/GDMLTransformer.kt | 4 +- .../kotlin/hep/dataforge/vision/gdml/units.kt | 70 --- .../hep/dataforge/vision/gdml/gdmlJVM.kt | 2 +- .../dataforge/vision/gdml/TestConvertor.kt | 8 +- .../dataforge/vision/gdml/bmanStatistics.kt | 2 +- visionforge-solid/build.gradle.kts | 15 +- .../kotlin/hep/dataforge/vision/solid/Box.kt | 15 +- .../hep/dataforge/vision/solid/Composite.kt | 18 +- .../hep/dataforge/vision/solid/ConeSegment.kt | 17 +- .../hep/dataforge/vision/solid/Convex.kt | 11 +- .../hep/dataforge/vision/solid/Extruded.kt | 31 +- .../dataforge/vision/solid/GeometryBuilder.kt | 14 +- .../hep/dataforge/vision/solid/PolyLine.kt | 12 +- .../hep/dataforge/vision/solid/Proxy.kt | 36 +- .../hep/dataforge/vision/solid/Solid.kt | 94 ++-- .../hep/dataforge/vision/solid/SolidGroup.kt | 24 +- .../hep/dataforge/vision/solid/SolidLabel.kt | 10 +- .../dataforge/vision/solid/SolidManager.kt | 59 +-- .../dataforge/vision/solid/SolidMaterial.kt | 39 +- .../hep/dataforge/vision/solid/Sphere.kt | 17 +- .../kotlin/hep/dataforge/vision/solid/Tube.kt | 15 +- .../hep/dataforge/vision/solid/geometry.kt | 43 +- .../dataforge/vision/solid/serialization.kt | 54 +-- .../vision/solid/specifications/Axes.kt | 14 +- .../vision/solid/specifications/Camera.kt | 30 +- .../solid/specifications/Canvas3DOptions.kt | 12 +- .../solid/transform/RemoveSingleChild.kt | 3 + .../dataforge/vision/solid/transform/UnRef.kt | 2 + .../hep/dataforge/vision/solid/ConvexTest.kt | 3 +- .../vision/solid/SerializationTest.kt | 23 +- .../hep/dataforge/vision/solid/geometryJs.kt | 6 +- .../vision/solid/three/ThreeFactory.kt | 3 +- .../vision/solid/three/ThreePlugin.kt | 17 +- .../vision/solid/three/ThreeProxyFactory.kt | 6 +- .../vision/solid/three/outputConfig.kt | 8 +- .../dataforge/vision/solid/fx/FX3DPlugin.kt | 2 +- .../vision/solid/fx/FXProxyFactory.kt | 10 +- .../dataforge/vision/solid/generateSchema.kt | 413 +++++++++--------- .../hep/dataforge/vision/solid/geometryJVM.kt | 12 +- 83 files changed, 874 insertions(+), 917 deletions(-) delete mode 100644 demo/build.gradle.kts create mode 100644 gradle.properties delete mode 100644 visionforge-gdml/src/commonMain/kotlin/hep/dataforge/vision/gdml/units.kt diff --git a/.gitignore b/.gitignore index 89cc712a..33607764 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,4 @@ out/ .gradle build/ - !gradle-wrapper.jar -gradle.properties \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index e69de29b..db566d2c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -0,0 +1,14 @@ +# Changelog + +## [Unreleased] +### Added + +### Changed + +### Deprecated + +### Removed + +### Fixed + +### Security diff --git a/build.gradle.kts b/build.gradle.kts index f2da0ea9..f2a94902 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,16 +1,12 @@ -import scientifik.useFx -import scientifik.useSerialization - -val dataforgeVersion by extra("0.1.8") +import ru.mipt.npm.gradle.useFx plugins { - id("scientifik.mpp") apply false - id("scientifik.jvm") apply false - id("scientifik.js") apply false - id("scientifik.publish") apply false - id("org.jetbrains.changelog") version "0.4.0" + id("ru.mipt.npm.project") } +val dataforgeVersion by extra("0.2.0-dev-3") +val ktorVersion by extra("1.4.1") + allprojects { repositories { mavenLocal() @@ -19,7 +15,7 @@ allprojects { } group = "hep.dataforge" - version = "0.1.5-dev-2" + version = "0.2.0-dev-1" } val githubProject by extra("visionforge") @@ -28,8 +24,17 @@ val fxVersion by extra("14") subprojects { if(name.startsWith("visionforge")) { - apply(plugin = "scientifik.publish") + apply() } - useSerialization() - useFx(scientifik.FXModule.CONTROLS, version = fxVersion) + afterEvaluate { + extensions.findByType()?.run { + useSerialization() + useFx(ru.mipt.npm.gradle.FXModule.CONTROLS, version = fxVersion) + } + } +} + +apiValidation { + validationDisabled = true + ignoredPackages.add("info.laht.threekt") } \ No newline at end of file diff --git a/demo/build.gradle.kts b/demo/build.gradle.kts deleted file mode 100644 index e69de29b..00000000 diff --git a/demo/gdml/build.gradle.kts b/demo/gdml/build.gradle.kts index 1ae0ffd9..b0a00e61 100644 --- a/demo/gdml/build.gradle.kts +++ b/demo/gdml/build.gradle.kts @@ -1,19 +1,24 @@ -import scientifik.DependencyConfiguration -import scientifik.FXModule -import scientifik.useFx +import ru.mipt.npm.gradle.DependencyConfiguration +import ru.mipt.npm.gradle.FXModule +import ru.mipt.npm.gradle.useFx plugins { - id("scientifik.mpp") - id("application") + id("ru.mipt.npm.mpp") + application } -val fxVersion: String by rootProject.extra -useFx(FXModule.CONTROLS, version = fxVersion, configuration = DependencyConfiguration.IMPLEMENTATION) +kscience { + val fxVersion: String by rootProject.extra + useFx(FXModule.CONTROLS, version = fxVersion, configuration = DependencyConfiguration.IMPLEMENTATION) + application() +} kotlin { jvm { - withJava() + afterEvaluate { + withJava() + } } js { @@ -27,7 +32,7 @@ kotlin { implementation(project(":visionforge-gdml")) } } - jsMain{ + jsMain { dependencies { implementation(project(":ui:bootstrap")) implementation(npm("react-file-drop", "3.0.6")) diff --git a/demo/gdml/src/commonMain/kotlin/hep/dataforge/vision/gdml/demo/cubes.kt b/demo/gdml/src/commonMain/kotlin/hep/dataforge/vision/gdml/demo/cubes.kt index 1f0b8cf9..e37ba142 100644 --- a/demo/gdml/src/commonMain/kotlin/hep/dataforge/vision/gdml/demo/cubes.kt +++ b/demo/gdml/src/commonMain/kotlin/hep/dataforge/vision/gdml/demo/cubes.kt @@ -1,6 +1,6 @@ package hep.dataforge.vision.gdml.demo -import scientifik.gdml.* +import kscience.gdml.* fun cubes(): GDML = GDML { diff --git a/demo/gdml/src/jsMain/kotlin/hep/dataforge/vision/gdml/demo/GDMLAppComponent.kt b/demo/gdml/src/jsMain/kotlin/hep/dataforge/vision/gdml/demo/GDMLAppComponent.kt index 9cd2c2bd..2392e042 100644 --- a/demo/gdml/src/jsMain/kotlin/hep/dataforge/vision/gdml/demo/GDMLAppComponent.kt +++ b/demo/gdml/src/jsMain/kotlin/hep/dataforge/vision/gdml/demo/GDMLAppComponent.kt @@ -1,7 +1,6 @@ package hep.dataforge.vision.gdml.demo import hep.dataforge.context.Context -import hep.dataforge.meta.set import hep.dataforge.names.Name import hep.dataforge.names.isEmpty import hep.dataforge.vision.Vision @@ -18,18 +17,18 @@ import hep.dataforge.vision.solid.specifications.Canvas3DOptions import hep.dataforge.vision.solid.three.ThreeCanvas import hep.dataforge.vision.solid.three.ThreeCanvasComponent import hep.dataforge.vision.solid.three.canvasControls +import kotlinx.browser.window import kotlinx.css.FlexBasis import kotlinx.css.Overflow import kotlinx.css.flex import kotlinx.css.overflow +import kscience.gdml.GDML +import kscience.gdml.decodeFromString import org.w3c.files.FileReader import org.w3c.files.get import react.RProps import react.dom.h1 -import scientifik.gdml.GDML -import scientifik.gdml.parse import styled.css -import kotlin.browser.window import kotlin.math.PI interface GDMLAppProps : RProps { @@ -58,10 +57,10 @@ val GDMLApp = component { props -> fun loadData(name: String, data: String) { val parsedVision = when { name.endsWith(".gdml") || name.endsWith(".xml") -> { - val gdml = GDML.parse(data) + val gdml = GDML.decodeFromString(data) gdml.toVision() } - name.endsWith(".json") -> SolidGroup.parseJson(data) + name.endsWith(".json") -> SolidGroup.decodeFromString(data) else -> { window.alert("File extension is not recognized: $name") error("File extension is not recognized: $name") diff --git a/demo/gdml/src/jsMain/kotlin/hep/dataforge/vision/gdml/demo/GdmlJsDemoApp.kt b/demo/gdml/src/jsMain/kotlin/hep/dataforge/vision/gdml/demo/GdmlJsDemoApp.kt index fc0478f0..cfb23cd5 100644 --- a/demo/gdml/src/jsMain/kotlin/hep/dataforge/vision/gdml/demo/GdmlJsDemoApp.kt +++ b/demo/gdml/src/jsMain/kotlin/hep/dataforge/vision/gdml/demo/GdmlJsDemoApp.kt @@ -3,15 +3,12 @@ package hep.dataforge.vision.gdml.demo import hep.dataforge.context.Global import hep.dataforge.js.Application import hep.dataforge.js.startApplication -import hep.dataforge.vision.gdml.GDMLTransformer -import hep.dataforge.vision.gdml.LUnit import hep.dataforge.vision.gdml.toVision -import hep.dataforge.vision.solid.SolidMaterial.Companion.MATERIAL_OPACITY_KEY +import kotlinx.browser.document import kotlinx.css.* import react.child import react.dom.render import styled.injectGlobal -import kotlin.browser.document private class GDMLDemoApp : Application { diff --git a/demo/gdml/src/jsMain/resources/index.html b/demo/gdml/src/jsMain/resources/index.html index fb53883c..14bb3178 100644 --- a/demo/gdml/src/jsMain/resources/index.html +++ b/demo/gdml/src/jsMain/resources/index.html @@ -7,7 +7,7 @@ - + diff --git a/demo/gdml/src/jvmMain/kotlin/hep/dataforge/vision/gdml/demo/readFile.kt b/demo/gdml/src/jvmMain/kotlin/hep/dataforge/vision/gdml/demo/readFile.kt index 355d6f98..e4344795 100644 --- a/demo/gdml/src/jvmMain/kotlin/hep/dataforge/vision/gdml/demo/readFile.kt +++ b/demo/gdml/src/jvmMain/kotlin/hep/dataforge/vision/gdml/demo/readFile.kt @@ -3,13 +3,12 @@ package hep.dataforge.vision.gdml.demo import hep.dataforge.meta.DFExperimental import hep.dataforge.meta.setItem import hep.dataforge.values.asValue -import hep.dataforge.vision.gdml.LUnit import hep.dataforge.vision.gdml.readFile import hep.dataforge.vision.gdml.toVision import hep.dataforge.vision.solid.SolidGroup import hep.dataforge.vision.solid.SolidManager import hep.dataforge.vision.solid.SolidMaterial -import scientifik.gdml.GDML +import kscience.gdml.GDML import java.io.File import java.util.zip.GZIPInputStream import java.util.zip.ZipInputStream @@ -32,19 +31,19 @@ fun SolidManager.Companion.readFile(file: File): SolidGroup = when { // } } } - file.extension == "json" -> SolidGroup.parseJson(file.readText()) + file.extension == "json" -> SolidGroup.decodeFromString(file.readText()) file.name.endsWith("json.zip") -> { file.inputStream().use { val unzip = ZipInputStream(it, Charsets.UTF_8) val text = unzip.readBytes().decodeToString() - SolidGroup.parseJson(text) + SolidGroup.decodeFromString(text) } } file.name.endsWith("json.gz") -> { file.inputStream().use { val unzip = GZIPInputStream(it) val text = unzip.readBytes().decodeToString() - SolidGroup.parseJson(text) + SolidGroup.decodeFromString(text) } } else -> error("Unknown extension ${file.extension}") diff --git a/demo/gdml/src/jvmMain/kotlin/hep/dataforge/vision/gdml/demo/saveToJson.kt b/demo/gdml/src/jvmMain/kotlin/hep/dataforge/vision/gdml/demo/saveToJson.kt index 5c0c09c6..798fd8b7 100644 --- a/demo/gdml/src/jvmMain/kotlin/hep/dataforge/vision/gdml/demo/saveToJson.kt +++ b/demo/gdml/src/jvmMain/kotlin/hep/dataforge/vision/gdml/demo/saveToJson.kt @@ -1,10 +1,10 @@ package hep.dataforge.vision.gdml.demo -import hep.dataforge.vision.gdml.LUnit import hep.dataforge.vision.gdml.readFile import hep.dataforge.vision.gdml.toVision -import hep.dataforge.vision.solid.stringify -import scientifik.gdml.GDML +import hep.dataforge.vision.solid.encodeToString +import kscience.gdml.GDML +import kscience.gdml.LUnit import java.io.File import java.nio.file.Paths @@ -21,7 +21,7 @@ fun main(args: Array) { lUnit = LUnit.CM } - val json = visual.stringify() + val json = visual.encodeToString() println(json) File(outputFileName).writeText(json) //File("D:\\Work\\Projects\\gdml.kt\\gdml-source\\cubes.json").writeText(json) diff --git a/demo/gdml/src/jvmTest/kotlin/hep/dataforge/vision/solid/FileSerializationTest.kt b/demo/gdml/src/jvmTest/kotlin/hep/dataforge/vision/solid/FileSerializationTest.kt index e10acbee..a1f9bab9 100644 --- a/demo/gdml/src/jvmTest/kotlin/hep/dataforge/vision/solid/FileSerializationTest.kt +++ b/demo/gdml/src/jvmTest/kotlin/hep/dataforge/vision/solid/FileSerializationTest.kt @@ -9,7 +9,7 @@ class FileSerializationTest { @Ignore fun testFileRead(){ val text = this::class.java.getResourceAsStream("/cubes.json").readBytes().decodeToString() - val visual = SolidGroup.parseJson(text) + val visual = SolidGroup.decodeFromString(text) visual["composite_001".asName()] } } \ No newline at end of file diff --git a/demo/muon-monitor/build.gradle.kts b/demo/muon-monitor/build.gradle.kts index ccb4d098..f4ba471d 100644 --- a/demo/muon-monitor/build.gradle.kts +++ b/demo/muon-monitor/build.gradle.kts @@ -1,43 +1,38 @@ import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation.Companion.MAIN_COMPILATION_NAME -import scientifik.jsDistDirectory plugins { - id("scientifik.mpp") - id("application") + id("ru.mipt.npm.mpp") + application } group = "ru.mipt.npm" -val ktorVersion = "1.3.2" +val ktorVersion: String by rootProject.extra + +kscience { + application() +} kotlin { + afterEvaluate { + val jsBrowserDistribution by tasks.getting - val installJS = tasks.getByName("jsBrowserDistribution") - - js { - browser { - dceTask { - dceOptions { - keep("ktor-ktor-io.\$\$importsForInline\$\$.ktor-ktor-io.io.ktor.utils.io") + jvm { + withJava() + compilations[MAIN_COMPILATION_NAME]?.apply { + tasks.getByName(processResourcesTaskName) { + dependsOn(jsBrowserDistribution) + afterEvaluate { + from(jsBrowserDistribution) + } } } - webpackTask { - mode = org.jetbrains.kotlin.gradle.targets.js.webpack.KotlinWebpackConfig.Mode.PRODUCTION - } + } } - jvm { - withJava() - compilations[MAIN_COMPILATION_NAME]?.apply { - tasks.getByName(processResourcesTaskName) { - dependsOn(installJS) - afterEvaluate { - from(project.jsDistDirectory) - } - } - } - + js { + useCommonJs() } sourceSets { @@ -58,14 +53,6 @@ kotlin { implementation(project(":ui:bootstrap")) implementation("io.ktor:ktor-client-js:$ktorVersion") implementation("io.ktor:ktor-client-serialization-js:$ktorVersion") - implementation(npm("text-encoding")) - implementation(npm("abort-controller")) - implementation(npm("bufferutil")) - implementation(npm("utf-8-validate")) - implementation(npm("fs")) -// implementation(npm("jquery")) -// implementation(npm("popper.js")) -// implementation(npm("react-is")) } } } diff --git a/demo/muon-monitor/src/jsMain/kotlin/ru/mipt/npm/muon/monitor/MMAppComponent.kt b/demo/muon-monitor/src/jsMain/kotlin/ru/mipt/npm/muon/monitor/MMAppComponent.kt index d08788c4..61deb655 100644 --- a/demo/muon-monitor/src/jsMain/kotlin/ru/mipt/npm/muon/monitor/MMAppComponent.kt +++ b/demo/muon-monitor/src/jsMain/kotlin/ru/mipt/npm/muon/monitor/MMAppComponent.kt @@ -4,6 +4,7 @@ import hep.dataforge.context.Context import hep.dataforge.names.Name import hep.dataforge.names.NameToken import hep.dataforge.names.isEmpty +import hep.dataforge.names.length import hep.dataforge.vision.Vision import hep.dataforge.vision.bootstrap.card import hep.dataforge.vision.react.component diff --git a/demo/muon-monitor/src/jsMain/kotlin/ru/mipt/npm/muon/monitor/MMDemoApp.kt b/demo/muon-monitor/src/jsMain/kotlin/ru/mipt/npm/muon/monitor/MMDemoApp.kt index 3fc00667..f4f93495 100644 --- a/demo/muon-monitor/src/jsMain/kotlin/ru/mipt/npm/muon/monitor/MMDemoApp.kt +++ b/demo/muon-monitor/src/jsMain/kotlin/ru/mipt/npm/muon/monitor/MMDemoApp.kt @@ -7,11 +7,11 @@ import hep.dataforge.vision.solid.SolidManager import io.ktor.client.HttpClient import io.ktor.client.features.json.JsonFeature import io.ktor.client.features.json.serializer.KotlinxSerializer +import kotlinx.browser.document import kotlinx.serialization.json.Json import react.child import react.dom.div import react.dom.render -import kotlin.browser.document private class MMDemoApp : Application { @@ -19,7 +19,7 @@ private class MMDemoApp : Application { private val connection = HttpClient { install(JsonFeature) { - serializer = KotlinxSerializer(Json(context = SolidManager.serialModule)) + serializer = KotlinxSerializer(Json { serializersModule = SolidManager.serialModule }) } } @@ -34,8 +34,8 @@ private class MMDemoApp : Application { div("container-fluid h-100") { child(MMApp) { attrs { - model = this@MMDemoApp.model - connection = this@MMDemoApp.connection + this.model = this@MMDemoApp.model + this.connection = this@MMDemoApp.connection this.context = context } } diff --git a/demo/muon-monitor/src/jsMain/resources/index.html b/demo/muon-monitor/src/jsMain/resources/index.html index 13624f25..9044e628 100644 --- a/demo/muon-monitor/src/jsMain/resources/index.html +++ b/demo/muon-monitor/src/jsMain/resources/index.html @@ -6,7 +6,7 @@ Three js demo for particle physics - + diff --git a/demo/muon-monitor/src/jvmMain/kotlin/ru/mipt/npm/muon/monitor/server/MMServer.kt b/demo/muon-monitor/src/jvmMain/kotlin/ru/mipt/npm/muon/monitor/server/MMServer.kt index d1e637b4..71d6b53a 100644 --- a/demo/muon-monitor/src/jvmMain/kotlin/ru/mipt/npm/muon/monitor/server/MMServer.kt +++ b/demo/muon-monitor/src/jvmMain/kotlin/ru/mipt/npm/muon/monitor/server/MMServer.kt @@ -10,6 +10,7 @@ import io.ktor.application.log import io.ktor.features.CallLogging import io.ktor.features.ContentNegotiation import io.ktor.features.DefaultHeaders +import io.ktor.http.ContentType import io.ktor.http.content.resources import io.ktor.http.content.static import io.ktor.response.respond @@ -19,6 +20,7 @@ import io.ktor.serialization.json import io.ktor.server.cio.CIO import io.ktor.server.engine.embeddedServer import io.ktor.util.KtorExperimentalAPI +import kotlinx.serialization.json.Json import org.apache.commons.math3.random.JDKRandomGenerator import ru.mipt.npm.muon.monitor.Model import ru.mipt.npm.muon.monitor.sim.Cos2TrackGenerator @@ -38,7 +40,7 @@ fun Application.module() { install(DefaultHeaders) install(CallLogging) install(ContentNegotiation) { - json(module = SolidManager.serialModule) + json(Json { serializersModule = SolidManager.serialModule }, ContentType.Application.Json) } install(Routing) { get("/event") { diff --git a/demo/spatial-showcase/build.gradle.kts b/demo/spatial-showcase/build.gradle.kts index b2816c18..40c4b04d 100644 --- a/demo/spatial-showcase/build.gradle.kts +++ b/demo/spatial-showcase/build.gradle.kts @@ -1,19 +1,22 @@ -import scientifik.DependencyConfiguration -import scientifik.FXModule -import scientifik.useFx +import ru.mipt.npm.gradle.* plugins { - id("scientifik.mpp") - id("application") + id("ru.mipt.npm.mpp") + application } -val fxVersion: String by rootProject.extra -useFx(FXModule.CONTROLS, version = fxVersion, configuration = DependencyConfiguration.IMPLEMENTATION) +kscience { + val fxVersion: String by rootProject.extra + useFx(FXModule.CONTROLS, version = fxVersion, configuration = DependencyConfiguration.IMPLEMENTATION) + application() +} kotlin { jvm { - withJava() + afterEvaluate { + withJava() + } } sourceSets { diff --git a/demo/spatial-showcase/src/commonMain/kotlin/hep/dataforge/vision/solid/demo/demo.kt b/demo/spatial-showcase/src/commonMain/kotlin/hep/dataforge/vision/solid/demo/demo.kt index a2786881..4f96f21b 100644 --- a/demo/spatial-showcase/src/commonMain/kotlin/hep/dataforge/vision/solid/demo/demo.kt +++ b/demo/spatial-showcase/src/commonMain/kotlin/hep/dataforge/vision/solid/demo/demo.kt @@ -8,6 +8,7 @@ import hep.dataforge.vision.Colors import hep.dataforge.vision.Vision import hep.dataforge.vision.solid.* import hep.dataforge.vision.solid.specifications.Canvas3DOptions +import hep.dataforge.vision.visible import kotlinx.coroutines.* import kotlin.math.PI import kotlin.math.cos diff --git a/demo/spatial-showcase/src/jsMain/resources/index.html b/demo/spatial-showcase/src/jsMain/resources/index.html index d709af37..278366e0 100644 --- a/demo/spatial-showcase/src/jsMain/resources/index.html +++ b/demo/spatial-showcase/src/jsMain/resources/index.html @@ -6,7 +6,7 @@ Three js demo for particle physics - +
diff --git a/gradle.properties b/gradle.properties new file mode 100644 index 00000000..930bba55 --- /dev/null +++ b/gradle.properties @@ -0,0 +1,9 @@ +kotlin.code.style=official +kotlin.parallel.tasks.in.project=true +kotlin.mpp.enableGranularSourceSetsMetadata=true +kotlin.native.enableDependencyPropagation=false +kotlin.mpp.stability.nowarn=true + +org.gradle.jvmargs=-XX:MaxMetaspaceSize=512m +org.gradle.parallel=true +systemProp.org.gradle.internal.publish.checksums.insecure=true \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 6c9a2247..12d38de6 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.6-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-6.6.1-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/playground/build.gradle.kts b/playground/build.gradle.kts index 4c71daab..4eeabfa2 100644 --- a/playground/build.gradle.kts +++ b/playground/build.gradle.kts @@ -7,12 +7,12 @@ repositories{ maven("https://kotlin.bintray.com/kotlinx") maven("https://dl.bintray.com/kotlin/kotlin-eap") maven("https://dl.bintray.com/mipt-npm/dataforge") - maven("https://dl.bintray.com/mipt-npm/scientifik") + maven("https://dl.bintray.com/mipt-npm/kscience") maven("https://dl.bintray.com/mipt-npm/dev") } kotlin { - js { + js(IR) { browser {} } diff --git a/settings.gradle.kts b/settings.gradle.kts index 187e5143..40fcab11 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1,32 +1,27 @@ pluginManagement { - val kotlinVersion = "1.3.72" - val toolsVersion = "0.5.2" + val kotlinVersion = "1.4.20-M1" + val toolsVersion = "0.6.3-dev-1.4.20-M1" repositories { mavenLocal() jcenter() gradlePluginPortal() - maven("https://kotlin.bintray.com/kotlinx") maven("https://dl.bintray.com/kotlin/kotlin-eap") + maven("https://dl.bintray.com/kotlin/kotlinx") maven("https://dl.bintray.com/mipt-npm/dataforge") - maven("https://dl.bintray.com/mipt-npm/scientifik") + maven("https://dl.bintray.com/mipt-npm/kscience") maven("https://dl.bintray.com/mipt-npm/dev") } plugins { + id("ru.mipt.npm.project") version toolsVersion + id("ru.mipt.npm.mpp") version toolsVersion + id("ru.mipt.npm.jvm") version toolsVersion + id("ru.mipt.npm.js") version toolsVersion + id("ru.mipt.npm.publish") version toolsVersion kotlin("jvm") version kotlinVersion - id("scientifik.mpp") version toolsVersion - id("scientifik.jvm") version toolsVersion - id("scientifik.js") version toolsVersion - id("scientifik.publish") version toolsVersion - } - - resolutionStrategy { - eachPlugin { - when (requested.id.id) { - "scientifik.mpp", "scientifik.publish", "scientifik.jvm", "scientifik.js" -> useModule("scientifik:gradle-tools:${toolsVersion}") - } - } + kotlin("js") version kotlinVersion + kotlin("multiplatform") version kotlinVersion } } @@ -34,11 +29,12 @@ pluginManagement { rootProject.name = "visionforge" + include( - ":ui", +// ":ui", ":ui:react", ":ui:ring", - ":ui:material", +// ":ui:material", ":ui:bootstrap", ":visionforge-core", ":visionforge-solid", diff --git a/ui/bootstrap/build.gradle.kts b/ui/bootstrap/build.gradle.kts index 598c1e56..b2400d0c 100644 --- a/ui/bootstrap/build.gradle.kts +++ b/ui/bootstrap/build.gradle.kts @@ -1,15 +1,9 @@ plugins { - id("scientifik.js") + id("ru.mipt.npm.js") } val dataforgeVersion: String by rootProject.extra -kotlin { - target { - useCommonJs() - } -} - dependencies{ api(project(":ui:react")) } \ No newline at end of file diff --git a/ui/bootstrap/src/main/kotlin/hep/dataforge/vision/bootstrap/bootstrap.kt b/ui/bootstrap/src/main/kotlin/hep/dataforge/vision/bootstrap/bootstrap.kt index f41c7ecc..14efcccb 100644 --- a/ui/bootstrap/src/main/kotlin/hep/dataforge/vision/bootstrap/bootstrap.kt +++ b/ui/bootstrap/src/main/kotlin/hep/dataforge/vision/bootstrap/bootstrap.kt @@ -2,6 +2,7 @@ package hep.dataforge.vision.bootstrap import hep.dataforge.names.Name import hep.dataforge.names.NameToken +import hep.dataforge.names.length import hep.dataforge.vision.Vision import hep.dataforge.vision.react.ObjectTree import kotlinx.html.* @@ -17,7 +18,7 @@ import styled.StyledDOMBuilder import styled.css import styled.styledDiv -inline fun TagConsumer.card(title: String, crossinline block: TagConsumer.() -> Unit) { +public inline fun TagConsumer.card(title: String, crossinline block: TagConsumer.() -> Unit) { div("card w-100") { div("card-body") { h3(classes = "card-title") { +title } @@ -26,7 +27,7 @@ inline fun TagConsumer.card(title: String, crossinline block: TagCo } } -inline fun RBuilder.card(title: String, classes: String? = null, crossinline block: RBuilder.() -> Unit) { +public inline fun RBuilder.card(title: String, classes: String? = null, crossinline block: RBuilder.() -> Unit) { div("card w-100 $classes") { div("card-body") { h3(classes = "card-title") { @@ -37,7 +38,7 @@ inline fun RBuilder.card(title: String, classes: String? = null, crossinline blo } } -fun TagConsumer.accordion(id: String, elements: List Unit>>) { +public fun TagConsumer.accordion(id: String, elements: List Unit>>) { div("container-fluid") { div("accordion") { this.id = id @@ -69,18 +70,18 @@ fun TagConsumer.accordion(id: String, elements: List Unit>> +public typealias AccordionBuilder = MutableList Unit>> -fun AccordionBuilder.entry(title: String, builder: DIV.() -> Unit) { +public fun AccordionBuilder.entry(title: String, builder: DIV.() -> Unit) { add(title to builder) } -fun TagConsumer.accordion(id: String, builder: AccordionBuilder.() -> Unit) { +public fun TagConsumer.accordion(id: String, builder: AccordionBuilder.() -> Unit) { val list = ArrayList Unit>>().apply(builder) accordion(id, list) } -fun RBuilder.accordion(id: String, elements: List.() -> Unit>>): ReactElement { +public fun RBuilder.accordion(id: String, elements: List.() -> Unit>>): ReactElement { return div("container-fluid") { div("accordion") { attrs { @@ -120,7 +121,7 @@ fun RBuilder.accordion(id: String, elements: List. } } -fun RBuilder.namecrumbs(name: Name?, rootTitle: String, link: (Name) -> Unit) { +public fun RBuilder.namecrumbs(name: Name?, rootTitle: String, link: (Name) -> Unit) { div("container-fluid p-0") { nav { attrs { @@ -160,20 +161,18 @@ fun RBuilder.namecrumbs(name: Name?, rootTitle: String, link: (Name) -> Unit) { } } -typealias RAccordionBuilder = MutableList.() -> Unit>> +public typealias RAccordionBuilder = MutableList.() -> Unit>> -fun RAccordionBuilder.entry(title: String, builder: RDOMBuilder
.() -> Unit) { +public fun RAccordionBuilder.entry(title: String, builder: RDOMBuilder
.() -> Unit) { add(title to builder) } -fun RBuilder.accordion(id: String, builder: RAccordionBuilder.() -> Unit): ReactElement { +public fun RBuilder.accordion(id: String, builder: RAccordionBuilder.() -> Unit): ReactElement { val list = ArrayList.() -> Unit>>().apply(builder) return accordion(id, list) } -fun joinStyles(vararg styles: String?) = styles.joinToString(separator = " ") { it ?: "" } - -enum class ContainerSize(val suffix: String) { +public enum class ContainerSize(public val suffix: String) { DEFAULT(""), SM("-sm"), MD("-md"), @@ -182,7 +181,7 @@ enum class ContainerSize(val suffix: String) { FLUID("-fluid") } -inline fun RBuilder.container( +public inline fun RBuilder.container( size: ContainerSize = ContainerSize.FLUID, block: StyledDOMBuilder
.() -> Unit ): ReactElement = styledDiv{ @@ -193,7 +192,7 @@ inline fun RBuilder.container( } -enum class GridMaxSize(val suffix: String) { +public enum class GridMaxSize(public val suffix: String) { NONE(""), SM("-sm"), MD("-md"), @@ -201,7 +200,7 @@ enum class GridMaxSize(val suffix: String) { XL("-xl") } -inline fun RBuilder.gridColumn( +public inline fun RBuilder.gridColumn( weight: Int? = null, maxSize: GridMaxSize = GridMaxSize.NONE, block: StyledDOMBuilder
.() -> Unit @@ -213,7 +212,7 @@ inline fun RBuilder.gridColumn( block() } -inline fun RBuilder.gridRow( +public inline fun RBuilder.gridRow( block: StyledDOMBuilder
.() -> Unit ): ReactElement = styledDiv{ css{ @@ -222,10 +221,10 @@ inline fun RBuilder.gridRow( block() } -fun Element.renderObjectTree( +public fun Element.renderObjectTree( vision: Vision, clickCallback: (Name) -> Unit = {} -) = render(this) { +): Unit = render(this) { card("Object tree") { child(ObjectTree) { attrs { diff --git a/ui/material/build.gradle.kts b/ui/material/build.gradle.kts index 78e48bc4..15eb5377 100644 --- a/ui/material/build.gradle.kts +++ b/ui/material/build.gradle.kts @@ -1,20 +1,14 @@ plugins { - id("scientifik.js") + id("ru.mipt.npm.js") } val dataforgeVersion: String by rootProject.extra -kotlin { - target { - useCommonJs() - } -} - dependencies{ api(project(":ui:react")) - api("subroh0508.net.kotlinmaterialui:core:0.4.0") - api("subroh0508.net.kotlinmaterialui:lab:0.4.0") + api("subroh0508.net.kotlinmaterialui:core:0.4.5") + api("subroh0508.net.kotlinmaterialui:lab:0.4.5") api(npm("@material-ui/core","4.9.14")) api(npm("@material-ui/lab","4.0.0-alpha.51")) //api(npm("@material-ui/icons","4.9.1")) diff --git a/ui/react/build.gradle.kts b/ui/react/build.gradle.kts index 64586c43..3fb049b5 100644 --- a/ui/react/build.gradle.kts +++ b/ui/react/build.gradle.kts @@ -1,11 +1,5 @@ plugins { - id("scientifik.js") -} - -kotlin { - target { - useCommonJs() - } + id("ru.mipt.npm.js") } val reactVersion by extra("16.13.1") @@ -14,7 +8,7 @@ dependencies{ api(project(":visionforge-core")) //api("org.jetbrains:kotlin-react:16.13.1-pre.104-kotlin-1.3.72") - api("org.jetbrains:kotlin-react-dom:$reactVersion-pre.104-kotlin-1.3.72") + api("org.jetbrains:kotlin-react-dom:$reactVersion-pre.123-kotlin-1.4.10") api(npm("react", reactVersion)) api(npm("react-dom", reactVersion)) diff --git a/ui/react/src/main/kotlin/hep/dataforge/vision/react/ConfigEditor.kt b/ui/react/src/main/kotlin/hep/dataforge/vision/react/ConfigEditor.kt index 712d3b60..b7c4407e 100644 --- a/ui/react/src/main/kotlin/hep/dataforge/vision/react/ConfigEditor.kt +++ b/ui/react/src/main/kotlin/hep/dataforge/vision/react/ConfigEditor.kt @@ -4,6 +4,7 @@ import hep.dataforge.meta.* import hep.dataforge.meta.descriptors.* import hep.dataforge.names.Name import hep.dataforge.names.NameToken +import hep.dataforge.names.lastOrNull import hep.dataforge.names.plus import hep.dataforge.values.Value import kotlinx.html.js.onClickFunction @@ -47,7 +48,7 @@ private fun RFBuilder.configEditorItem(props: ConfigEditorItemProps) { val defaultItem = props.default?.get(props.name) var actualItem: MetaItem? by state { item ?: defaultItem ?: descriptorItem?.defaultItem() } - val token = props.name.last()?.toString() ?: "Properties" + val token = props.name.lastOrNull()?.toString() ?: "Properties" fun update() { item = props.root[props.name] diff --git a/ui/react/src/main/kotlin/hep/dataforge/vision/react/MetaViewer.kt b/ui/react/src/main/kotlin/hep/dataforge/vision/react/MetaViewer.kt index e5a628b4..5f98e40f 100644 --- a/ui/react/src/main/kotlin/hep/dataforge/vision/react/MetaViewer.kt +++ b/ui/react/src/main/kotlin/hep/dataforge/vision/react/MetaViewer.kt @@ -9,6 +9,7 @@ import hep.dataforge.meta.descriptors.get import hep.dataforge.meta.get import hep.dataforge.names.Name import hep.dataforge.names.NameToken +import hep.dataforge.names.lastOrNull import hep.dataforge.names.plus import kotlinx.html.js.onClickFunction import org.w3c.dom.events.Event @@ -43,7 +44,7 @@ private fun RFBuilder.metaViewerItem(props: MetaViewerProps) { val descriptorItem: ItemDescriptor? = props.descriptor?.get(props.name) val actualItem = item ?: descriptorItem?.defaultItem() - val token = props.name.last()?.toString() ?: "Meta" + val token = props.name.lastOrNull()?.toString() ?: "Meta" val expanderClick: (Event) -> Unit = { expanded = !expanded diff --git a/ui/react/src/main/kotlin/hep/dataforge/vision/react/ObjectTree.kt b/ui/react/src/main/kotlin/hep/dataforge/vision/react/ObjectTree.kt index 3b2112fb..ece2a32b 100644 --- a/ui/react/src/main/kotlin/hep/dataforge/vision/react/ObjectTree.kt +++ b/ui/react/src/main/kotlin/hep/dataforge/vision/react/ObjectTree.kt @@ -1,6 +1,7 @@ package hep.dataforge.vision.react import hep.dataforge.names.Name +import hep.dataforge.names.lastOrNull import hep.dataforge.names.plus import hep.dataforge.names.startsWith import hep.dataforge.vision.Vision @@ -42,7 +43,7 @@ private fun RFBuilder.objectTree(props: ObjectTreeProps): Unit { } } - val token = props.name.last()?.toString() ?: "World" + val token = props.name.lastOrNull()?.toString() ?: "World" val obj = props.obj //display as node if any child is visible diff --git a/ui/ring/build.gradle.kts b/ui/ring/build.gradle.kts index 6cb807a3..167743be 100644 --- a/ui/ring/build.gradle.kts +++ b/ui/ring/build.gradle.kts @@ -1,22 +1,13 @@ plugins { - id("scientifik.js") + id("ru.mipt.npm.js") } val dataforgeVersion: String by rootProject.extra -kotlin { - target { - useCommonJs() - } -} - - dependencies{ api(project(":ui:react")) implementation(npm("@jetbrains/logos", "1.1.6")) implementation(npm("@jetbrains/ring-ui", "3.0.13")) - - implementation(npm("svg-inline-loader", "0.8.0")) } \ No newline at end of file diff --git a/visionforge-core/build.gradle.kts b/visionforge-core/build.gradle.kts index 2ef4cad5..546587d2 100644 --- a/visionforge-core/build.gradle.kts +++ b/visionforge-core/build.gradle.kts @@ -1,13 +1,10 @@ plugins { - id("scientifik.mpp") + id("ru.mipt.npm.mpp") } val dataforgeVersion: String by rootProject.extra kotlin { - js { - useCommonJs() - } sourceSets { commonMain { @@ -30,15 +27,15 @@ kotlin { jsMain { dependencies { api("hep.dataforge:dataforge-output-html:$dataforgeVersion") - api("org.jetbrains.kotlinx:kotlinx-html:0.6.12") + api("org.jetbrains.kotlinx:kotlinx-html:0.7.2") //api("org.jetbrains:kotlin-extensions:1.0.1-pre.105-kotlin-1.3.72") //api("org.jetbrains:kotlin-css-js:1.0.0-pre.105-kotlin-1.3.72") - api("org.jetbrains:kotlin-styled:1.0.0-pre.104-kotlin-1.3.72") + api("org.jetbrains:kotlin-styled:5.2.0-pre.123-kotlin-1.4.10") api(npm("core-js", "2.6.5")) api(npm("inline-style-prefixer", "5.1.0")) - api(npm("styled-components", "4.3.2")) + api(npm("styled-components", "5.2.0")) //api(project(":ringui-wrapper")) } } diff --git a/visionforge-core/src/commonMain/kotlin/hep/dataforge/properties/ConfigProperty.kt b/visionforge-core/src/commonMain/kotlin/hep/dataforge/properties/ConfigProperty.kt index 11936eda..550d39a7 100644 --- a/visionforge-core/src/commonMain/kotlin/hep/dataforge/properties/ConfigProperty.kt +++ b/visionforge-core/src/commonMain/kotlin/hep/dataforge/properties/ConfigProperty.kt @@ -4,7 +4,7 @@ import hep.dataforge.meta.* import hep.dataforge.names.Name @DFExperimental -class ConfigProperty(val config: Config, val name: Name) : Property?> { +internal class ConfigProperty(val config: Config, val name: Name) : Property?> { override var value: MetaItem<*>? get() = config[name] set(value) { diff --git a/visionforge-core/src/commonMain/kotlin/hep/dataforge/vision/AbstractVision.kt b/visionforge-core/src/commonMain/kotlin/hep/dataforge/vision/AbstractVision.kt index a025a87a..68e6ee85 100644 --- a/visionforge-core/src/commonMain/kotlin/hep/dataforge/vision/AbstractVision.kt +++ b/visionforge-core/src/commonMain/kotlin/hep/dataforge/vision/AbstractVision.kt @@ -87,13 +87,13 @@ abstract class AbstractVision : Vision { /** * Reset all properties to their default values */ - fun resetProperties() { + public fun resetProperties() { properties?.removeListener(this) properties = null } - companion object { - val descriptor = NodeDescriptor { + public companion object { + public val descriptor: NodeDescriptor = NodeDescriptor { value(STYLE_KEY) { type(ValueType.STRING) multiple = true diff --git a/visionforge-core/src/commonMain/kotlin/hep/dataforge/vision/AbstractVisionGroup.kt b/visionforge-core/src/commonMain/kotlin/hep/dataforge/vision/AbstractVisionGroup.kt index d1d7f523..f2c343d6 100644 --- a/visionforge-core/src/commonMain/kotlin/hep/dataforge/vision/AbstractVisionGroup.kt +++ b/visionforge-core/src/commonMain/kotlin/hep/dataforge/vision/AbstractVisionGroup.kt @@ -1,9 +1,6 @@ package hep.dataforge.vision -import hep.dataforge.names.Name -import hep.dataforge.names.NameToken -import hep.dataforge.names.asName -import hep.dataforge.names.isEmpty +import hep.dataforge.names.* import kotlinx.serialization.Transient @@ -105,7 +102,7 @@ abstract class AbstractVisionGroup : AbstractVision(), MutableVisionGroup { return when { name.isEmpty() -> error("Should be unreachable") name.length == 1 -> { - val token = name.first()!! + val token = name.tokens.first() when (val current = children[token]) { null -> createGroup().also { child -> attach(child) @@ -115,7 +112,7 @@ abstract class AbstractVisionGroup : AbstractVision(), MutableVisionGroup { else -> error("Can't create group with name $name because it exists and not a group") } } - else -> createGroups(name.first()!!.asName()).createGroups(name.cutFirst()) + else -> createGroups(name.tokens.first().asName()).createGroups(name.cutFirst()) } } @@ -131,7 +128,7 @@ abstract class AbstractVisionGroup : AbstractVision(), MutableVisionGroup { } } name.length == 1 -> { - val token = name.first()!! + val token = name.tokens.first() if (child == null) { removeChild(token) } else { @@ -142,7 +139,7 @@ abstract class AbstractVisionGroup : AbstractVision(), MutableVisionGroup { else -> { //TODO add safety check val parent = (get(name.cutLast()) as? MutableVisionGroup) ?: createGroups(name.cutLast()) - parent[name.last()!!.asName()] = child + parent[name.tokens.last().asName()] = child } } childrenChanged(name, child) diff --git a/visionforge-core/src/commonMain/kotlin/hep/dataforge/vision/StyleSheet.kt b/visionforge-core/src/commonMain/kotlin/hep/dataforge/vision/StyleSheet.kt index d4199657..0a5f27e5 100644 --- a/visionforge-core/src/commonMain/kotlin/hep/dataforge/vision/StyleSheet.kt +++ b/visionforge-core/src/commonMain/kotlin/hep/dataforge/vision/StyleSheet.kt @@ -8,20 +8,23 @@ import hep.dataforge.names.asName import kotlinx.serialization.* import kotlinx.serialization.builtins.MapSerializer import kotlinx.serialization.builtins.serializer +import kotlinx.serialization.descriptors.SerialDescriptor +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder /** * A container for styles */ @Serializable -class StyleSheet private constructor(private val styleMap: MutableMap = LinkedHashMap()) { +public class StyleSheet private constructor(private val styleMap: MutableMap = LinkedHashMap()) { @Transient internal var owner: Vision? = null - constructor(owner: Vision) : this() { + public constructor(owner: Vision) : this() { this.owner = owner } - val items: Map get() = styleMap + public val items: Map get() = styleMap private fun Vision.styleChanged(key: String, oldStyle: Meta?, newStyle: Meta?) { @@ -38,14 +41,14 @@ class StyleSheet private constructor(private val styleMap: MutableMap Unit) { + public operator fun set(key: String, builder: MetaBuilder.() -> Unit) { val newStyle = get(key)?.edit(builder) ?: Meta(builder) set(key, newStyle.seal()) } + @ExperimentalSerializationApi @Serializer(StyleSheet::class) - companion object : KSerializer { + public companion object : KSerializer { private val mapSerializer = MapSerializer(String.serializer(), MetaSerializer) override val descriptor: SerialDescriptor get() = mapSerializer.descriptor @@ -91,14 +95,14 @@ class StyleSheet private constructor(private val styleMap: MutableMap> { +public fun Vision.getStyleItems(name: Name): Sequence> { return styles.asSequence().map { resolveStyle(it) }.map { @@ -109,4 +113,4 @@ fun Vision.getStyleItems(name: Name): Sequence> { /** * Collect all styles for this object in a single laminate */ -val Vision.allStyles: Laminate get() = Laminate(styles.mapNotNull(::resolveStyle)) \ No newline at end of file +public val Vision.allStyles: Laminate get() = Laminate(styles.mapNotNull(::resolveStyle)) \ No newline at end of file diff --git a/visionforge-core/src/commonMain/kotlin/hep/dataforge/vision/Vision.kt b/visionforge-core/src/commonMain/kotlin/hep/dataforge/vision/Vision.kt index 4d819910..7ccdd81e 100644 --- a/visionforge-core/src/commonMain/kotlin/hep/dataforge/vision/Vision.kt +++ b/visionforge-core/src/commonMain/kotlin/hep/dataforge/vision/Vision.kt @@ -5,7 +5,9 @@ import hep.dataforge.names.Name import hep.dataforge.names.asName import hep.dataforge.names.toName import hep.dataforge.provider.Type +import hep.dataforge.values.asValue import hep.dataforge.vision.Vision.Companion.TYPE +import hep.dataforge.vision.Vision.Companion.VISIBLE_KEY import kotlinx.serialization.PolymorphicSerializer import kotlinx.serialization.Transient @@ -13,28 +15,28 @@ import kotlinx.serialization.Transient * A root type for display hierarchy */ @Type(TYPE) -interface Vision : Configurable { +public interface Vision : Configurable { /** * The parent object of this one. If null, this one is a root. */ @Transient - var parent: VisionGroup? + public var parent: VisionGroup? /** * Nullable version of [config] used to check if this [Vision] has custom properties */ - val properties: Config? + public val properties: Config? /** * All properties including styles and prototypes if present, including inherited ones */ - fun getAllProperties(): Laminate + public fun getAllProperties(): Laminate /** * Get property (including styles). [inherit] toggles parent node property lookup */ - fun getProperty(name: Name, inherit: Boolean): MetaItem<*>? + public fun getProperty(name: Name, inherit: Boolean): MetaItem<*>? /** * Ger a property including inherited values @@ -44,46 +46,55 @@ interface Vision : Configurable { /** * Trigger property invalidation event. If [name] is empty, notify that the whole object is changed */ - fun propertyChanged(name: Name): Unit + public fun propertyChanged(name: Name): Unit /** * Add listener triggering on property change */ - fun onPropertyChange(owner: Any?, action: (Name) -> Unit): Unit + public fun onPropertyChange(owner: Any?, action: (Name) -> Unit): Unit /** * Remove change listeners with given owner. */ - fun removeChangeListener(owner: Any?) + public fun removeChangeListener(owner: Any?) /** * List of names of styles applied to this object. Order matters. Not inherited. */ - var styles: List - get() = properties[STYLE_KEY].stringList + public var styles: List + get() = properties[STYLE_KEY]?.stringList?: emptyList() set(value) { config[STYLE_KEY] = value } - companion object { - const val TYPE = "vision" - val STYLE_KEY = "@style".asName() + public companion object { + public const val TYPE: String = "vision" + public val STYLE_KEY: Name = "@style".asName() private val VISION_SERIALIZER = PolymorphicSerializer(Vision::class) - fun serializer() = VISION_SERIALIZER + public fun serializer(): PolymorphicSerializer = VISION_SERIALIZER + + public val VISIBLE_KEY: Name = "visible".asName() } } /** * Get [Vision] property using key as a String */ -fun Vision.getProperty(key: String, inherit: Boolean = true): MetaItem<*>? = +public fun Vision.getProperty(key: String, inherit: Boolean = true): MetaItem<*>? = getProperty(key.toName(), inherit) /** * Find a style with given name for given [Vision]. The style is not necessary applied to this [Vision]. */ -tailrec fun Vision.resolveStyle(name: String): Meta? = +public tailrec fun Vision.resolveStyle(name: String): Meta? = (this as? VisionGroup)?.styleSheet?.get(name) ?: parent?.resolveStyle(name) + +/** + * Control visibility of the element + */ +public var Vision.visible: Boolean? + get() = getItem(VISIBLE_KEY).boolean + set(value) = setItem(VISIBLE_KEY, value?.asValue()) diff --git a/visionforge-core/src/commonMain/kotlin/hep/dataforge/vision/VisionGroup.kt b/visionforge-core/src/commonMain/kotlin/hep/dataforge/vision/VisionGroup.kt index 43b964f2..3035e18d 100644 --- a/visionforge-core/src/commonMain/kotlin/hep/dataforge/vision/VisionGroup.kt +++ b/visionforge-core/src/commonMain/kotlin/hep/dataforge/vision/VisionGroup.kt @@ -3,14 +3,18 @@ package hep.dataforge.vision import hep.dataforge.names.* import hep.dataforge.provider.Provider +public interface VisionContainer{ + public operator fun get(name: Name): V? +} + /** * Represents a group of [Vision] instances */ -interface VisionGroup : Provider, Vision { +public interface VisionGroup : Provider, Vision, VisionContainer { /** * A map of top level named children */ - val children: Map + public val children: Map override val defaultTarget: String get() = Vision.TYPE @@ -18,17 +22,17 @@ interface VisionGroup : Provider, Vision { * A stylesheet for this group and its descendants. Stylesheet is not applied directly, * but instead is just a repository for named configurations. */ - val styleSheet: StyleSheet? + public val styleSheet: StyleSheet? /** * A map of direct children for specific target * (currently "visual" or "style") */ - override fun provideTop(target: String): Map = + override fun content(target: String): Map = when (target) { Vision.TYPE -> children.flatMap { (key, value) -> val res: Map = if (value is VisionGroup) { - value.provideTop(target).mapKeys { key + it.key } + value.content(target).mapKeys { key + it.key } } else { mapOf(key.asName() to value) } @@ -38,18 +42,18 @@ interface VisionGroup : Provider, Vision { else -> emptyMap() } - operator fun get(name: Name): Vision? { + public override operator fun get(name: Name): Vision? { return when { name.isEmpty() -> this - name.length == 1 -> children[name.first()!!] - else -> (children[name.first()!!] as? VisionGroup)?.get(name.cutFirst()) + name.length == 1 -> children[name.tokens.first()] + else -> (children[name.tokens.first()] as? VisionGroup)?.get(name.cutFirst()) } } /** * A fix for serialization bug that writes all proper parents inside the tree after deserialization */ - fun attachChildren() { + public fun attachChildren() { styleSheet?.owner = this children.values.forEach { it.parent = this @@ -57,41 +61,45 @@ interface VisionGroup : Provider, Vision { } } - companion object { - const val STYLE_TARGET = "style" + public companion object { + public const val STYLE_TARGET: String = "style" } } /** * Iterate over children of this group */ -operator fun VisionGroup.iterator(): Iterator = children.values.iterator() +public operator fun VisionGroup.iterator(): Iterator = children.values.iterator() -val VisionGroup.isEmpty: Boolean get() = this.children.isEmpty() +public val VisionGroup.isEmpty: Boolean get() = this.children.isEmpty() + +public interface VisionContainerBuilder{ + public operator fun set(name: Name, child: V?) +} /** * Mutable version of [VisionGroup] */ -interface MutableVisionGroup : VisionGroup { +public interface MutableVisionGroup : VisionGroup, VisionContainerBuilder { /** * Add listener for children structure change. * @param owner the handler to properly remove listeners * @param action First argument of the action is the name of changed child. Second argument is the new value of the object. */ - fun onChildrenChange(owner: Any?, action: (Name, Vision?) -> Unit) + public fun onChildrenChange(owner: Any?, action: (Name, Vision?) -> Unit) /** * Remove children change listener */ - fun removeChildrenChangeListener(owner: Any?) + public fun removeChildrenChangeListener(owner: Any?) - operator fun set(name: Name, child: Vision?) +// public operator fun set(name: Name, child: Vision?) } -operator fun VisionGroup.get(str: String?): Vision? = get(str?.toName() ?: Name.EMPTY) +public operator fun VisionContainer.get(str: String?): V? = get(str?.toName() ?: Name.EMPTY) -operator fun MutableVisionGroup.set(token: NameToken, child: Vision?): Unit = set(token.asName(), child) -operator fun MutableVisionGroup.set(key: String, child: Vision?): Unit = set(key.toName(), child) +public operator fun VisionContainerBuilder.set(token: NameToken, child: V?): Unit = set(token.asName(), child) +public operator fun VisionContainerBuilder.set(key: String, child: V?): Unit = set(key.toName(), child) -fun MutableVisionGroup.removeAll() = children.keys.map { it.asName() }.forEach { this[it] = null } \ No newline at end of file +public fun MutableVisionGroup.removeAll(): Unit = children.keys.map { it.asName() }.forEach { this[it] = null } \ No newline at end of file diff --git a/visionforge-core/src/commonMain/kotlin/hep/dataforge/vision/VisionManager.kt b/visionforge-core/src/commonMain/kotlin/hep/dataforge/vision/VisionManager.kt index 6bf7291c..39f7096f 100644 --- a/visionforge-core/src/commonMain/kotlin/hep/dataforge/vision/VisionManager.kt +++ b/visionforge-core/src/commonMain/kotlin/hep/dataforge/vision/VisionManager.kt @@ -3,35 +3,37 @@ package hep.dataforge.vision import hep.dataforge.context.* import hep.dataforge.meta.* import hep.dataforge.meta.descriptors.NodeDescriptor +import hep.dataforge.names.Name import hep.dataforge.names.toName +import kotlinx.serialization.ExperimentalSerializationApi import kotlinx.serialization.KSerializer -import kotlinx.serialization.UnstableDefault import kotlinx.serialization.json.Json -import kotlinx.serialization.json.JsonConfiguration -import kotlinx.serialization.modules.SerialModule import kotlinx.serialization.modules.SerializersModule +import kotlinx.serialization.modules.polymorphic +import kotlinx.serialization.modules.subclass import kotlin.reflect.KClass @DFExperimental -interface VisionForm { - val type: KClass - val serializer: KSerializer +public interface VisionForm { + public val type: KClass + public val serializer: KSerializer - val name get() = serializer.descriptor.serialName.toName() + public val name: Name + get() = serializer.descriptor.serialName.toName() /** * Apply a patch to given [Vision] */ - fun patch(obj: T, meta: Meta) + public fun patch(obj: T, meta: Meta) - companion object { - const val TYPE = "visionForm" + public companion object { + public const val TYPE: String = "visionForm" } } @DFExperimental -object SimpleGroupForm: VisionForm{ +public object SimpleGroupForm : VisionForm { override val type: KClass = SimpleVisionGroup::class override val serializer: KSerializer = SimpleVisionGroup.serializer() @@ -42,86 +44,93 @@ object SimpleGroupForm: VisionForm{ } @DFExperimental -fun VisionForm.visionToMeta(vision: T, module: SerialModule, descriptor: NodeDescriptor? = null): Meta { - val engine = Json(VisionManager.jsonConfiguration, module) - val json = engine.toJson(serializer, vision) +public fun VisionForm.visionToMeta( + vision: T, + module: SerializersModule, + descriptor: NodeDescriptor? = null, +): Meta { + val engine = Json(VisionManager.jsonConfiguration) { serializersModule = module } + val json = engine.encodeToJsonElement(serializer, vision) return json.toMetaItem(descriptor).node!! } @DFExperimental -fun VisionForm.buildVision(meta: Meta, module: SerialModule, descriptor: NodeDescriptor? = null): T { - val engine = Json(VisionManager.jsonConfiguration, module) +public fun VisionForm.buildVision( + meta: Meta, + module: SerializersModule, + descriptor: NodeDescriptor? = null, +): T { + val engine = Json(VisionManager.jsonConfiguration) { serializersModule = module } val json = meta.toJson(descriptor) - return engine.fromJson(serializer, json) + return engine.decodeFromJsonElement(serializer, json) } @DFExperimental -class VisionManager(meta: Meta) : AbstractPlugin(meta) { +public class VisionManager(meta: Meta) : AbstractPlugin(meta) { override val tag: PluginTag get() = Companion.tag /** * Create a list of factories on first call and cache it */ private val forms by lazy { - context.content>(VisionForm.TYPE).mapKeys { it.value.type } + context.gather>(VisionForm.TYPE).mapKeys { it.value.type } } - val visionSerialModule + public val visionSerialModule: SerializersModule get() = SerializersModule { include(defaultSerialModule) - context.content(VISION_SERIAL_MODULE_TARGET).values.forEach { + context.gather(VISION_SERIAL_MODULE_TARGET).values.forEach { include(it) } } @Suppress("UNCHECKED_CAST") - fun resolveVisionForm(type: KClass): VisionForm? = + public fun resolveVisionForm(type: KClass): VisionForm = forms[type] as VisionForm - inline fun buildSpecificVision(meta: Meta): T { + public inline fun buildSpecificVision(meta: Meta): T { val factory = resolveVisionForm(T::class) ?: error("Could not resolve a form for ${meta["type"].string}") return factory.buildVision(meta, visionSerialModule) } - fun buildVision(meta: Meta): Vision { + @OptIn(ExperimentalSerializationApi::class) + public fun buildVision(meta: Meta): Vision { val type = meta["type"].string ?: Vision.serializer().descriptor.serialName val form = forms.values.find { it.name.toString() == type } ?: error("Could not resolve a form for type $type") return form.buildVision(meta, visionSerialModule) } - fun writeVisionToMeta(vision: T): Meta { + public fun writeVisionToMeta(vision: T): Meta { val form = resolveVisionForm(vision::class) ?: error("Could not resolve a form for $vision") - val engine = Json(VisionManager.jsonConfiguration, visionSerialModule) - val json = engine.toJson(form.serializer,vision) + val engine = Json(jsonConfiguration) { serializersModule = visionSerialModule } + val json = engine.encodeToJsonElement(form.serializer, vision) return json.toMetaItem().node!! } - fun patchVision(vision: Vision, meta: Meta) { + public fun patchVision(vision: Vision, meta: Meta) { val form = resolveVisionForm(vision::class) ?: error("Could not resolve a form for $vision") form.patch(vision, meta) } - companion object : PluginFactory { + public companion object : PluginFactory { override val tag: PluginTag = PluginTag(name = "vision", group = PluginTag.DATAFORGE_GROUP) override val type: KClass = VisionManager::class - const val VISION_SERIAL_MODULE_TARGET = "visionSerialModule" + public const val VISION_SERIAL_MODULE_TARGET: String = "visionSerialModule" override fun invoke(meta: Meta, context: Context): VisionManager = VisionManager(meta) - @OptIn(UnstableDefault::class) - val jsonConfiguration = JsonConfiguration( - prettyPrint = true, - useArrayPolymorphism = false, - encodeDefaults = false, + public val jsonConfiguration: Json = Json { + prettyPrint = true + useArrayPolymorphism = false + encodeDefaults = false ignoreUnknownKeys = true - ) + } - val defaultSerialModule = SerializersModule { - polymorphic(Vision::class, VisionGroup::class) { + public val defaultSerialModule: SerializersModule = SerializersModule { + polymorphic(Vision::class) { subclass(SimpleVisionGroup.serializer()) } } - } } \ No newline at end of file diff --git a/visionforge-core/src/commonMain/kotlin/hep/dataforge/vision/valueWidget.kt b/visionforge-core/src/commonMain/kotlin/hep/dataforge/vision/valueWidget.kt index 4edc70e4..f563d87c 100644 --- a/visionforge-core/src/commonMain/kotlin/hep/dataforge/vision/valueWidget.kt +++ b/visionforge-core/src/commonMain/kotlin/hep/dataforge/vision/valueWidget.kt @@ -1,27 +1,27 @@ package hep.dataforge.vision -import hep.dataforge.meta.Meta +import hep.dataforge.meta.* import hep.dataforge.meta.descriptors.ValueDescriptor -import hep.dataforge.meta.descriptors.setAttribute -import hep.dataforge.meta.get -import hep.dataforge.meta.node -import hep.dataforge.meta.string -import hep.dataforge.names.toName +import hep.dataforge.meta.descriptors.attributes /** * Extension property to access the "widget" key of [ValueDescriptor] */ -var ValueDescriptor.widget: Meta +public var ValueDescriptor.widget: Meta get() = attributes["widget"].node ?: Meta.EMPTY set(value) { - setAttribute("widget".toName(), value) + attributes { + set("widget", value) + } } /** * Extension property to access the "widget.type" key of [ValueDescriptor] */ -var ValueDescriptor.widgetType: String? +public var ValueDescriptor.widgetType: String? get() = attributes["widget.type"].string set(value) { - setAttribute("widget.type".toName(), value) + attributes{ + set("widget.type", value) + } } \ No newline at end of file diff --git a/visionforge-core/src/commonMain/kotlin/hep/dataforge/vision/visitor/StatisticsVisitor.kt b/visionforge-core/src/commonMain/kotlin/hep/dataforge/vision/visitor/StatisticsVisitor.kt index 21842994..89877fe6 100644 --- a/visionforge-core/src/commonMain/kotlin/hep/dataforge/vision/visitor/StatisticsVisitor.kt +++ b/visionforge-core/src/commonMain/kotlin/hep/dataforge/vision/visitor/StatisticsVisitor.kt @@ -1,6 +1,7 @@ package hep.dataforge.vision.visitor import hep.dataforge.names.Name +import hep.dataforge.names.length import hep.dataforge.vision.Vision import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.Job diff --git a/visionforge-core/src/jvmMain/kotlin/hep/dataforge/vision/editor/FXMeta.kt b/visionforge-core/src/jvmMain/kotlin/hep/dataforge/vision/editor/FXMeta.kt index 04d954b6..84a286ed 100644 --- a/visionforge-core/src/jvmMain/kotlin/hep/dataforge/vision/editor/FXMeta.kt +++ b/visionforge-core/src/jvmMain/kotlin/hep/dataforge/vision/editor/FXMeta.kt @@ -4,10 +4,7 @@ import hep.dataforge.meta.* import hep.dataforge.meta.descriptors.ItemDescriptor import hep.dataforge.meta.descriptors.NodeDescriptor import hep.dataforge.meta.descriptors.ValueDescriptor -import hep.dataforge.names.Name -import hep.dataforge.names.NameToken -import hep.dataforge.names.asName -import hep.dataforge.names.withIndex +import hep.dataforge.names.* import hep.dataforge.values.Null import hep.dataforge.values.Value import javafx.beans.binding.ListBinding @@ -137,12 +134,12 @@ class FXMetaNode>( } } -class FXMetaValue>( +public class FXMetaValue>( override val name: NameToken, override val parent: FXMetaNode ) : FXMeta() { - val descriptorProperty = parent.descriptorProperty.objectBinding { + public val descriptorProperty = parent.descriptorProperty.objectBinding { it?.values?.get(name.body) } @@ -153,24 +150,24 @@ class FXMetaValue>( //private val innerValueProperty = SimpleObjectProperty(value) - val valueProperty = descriptorProperty.objectBinding { descriptor -> + public val valueProperty = descriptorProperty.objectBinding { descriptor -> parent.node[name].value ?: descriptor?.default } override val hasValue: ObservableBooleanValue = parent.nodeProperty.booleanBinding { it[name] != null } - val value by valueProperty + public val value by valueProperty override val descriptionProperty = descriptorProperty.stringBinding { it?.info ?: "" } } -fun > FXMetaNode.remove(name: NameToken) { +public fun > FXMetaNode.remove(name: NameToken) { node?.remove(name.asName()) children.invalidate() } private fun > M.createEmptyNode(token: NameToken, append: Boolean): M { - return if (append && token.index.isNotEmpty()) { + return if (append && token.hasIndex()) { val name = token.asName() val index = (getIndexed(name).keys.mapNotNull { it.toIntOrNull() }.max() ?: -1) + 1 val newName = name.withIndex(index.toString()) diff --git a/visionforge-gdml/build.gradle.kts b/visionforge-gdml/build.gradle.kts index 874523ac..ebb6a865 100644 --- a/visionforge-gdml/build.gradle.kts +++ b/visionforge-gdml/build.gradle.kts @@ -1,5 +1,5 @@ plugins { - id("scientifik.mpp") + id("ru.mipt.npm.mpp") } kotlin { @@ -7,7 +7,7 @@ kotlin { val commonMain by getting { dependencies { api(project(":visionforge-solid")) - api("scientifik:gdml:0.1.8") + api("kscience.gdml:gdml:0.2.0-dev-2") } } } diff --git a/visionforge-gdml/src/commonMain/kotlin/hep/dataforge/vision/gdml/GDMLTransformer.kt b/visionforge-gdml/src/commonMain/kotlin/hep/dataforge/vision/gdml/GDMLTransformer.kt index ceecd768..3995c92f 100644 --- a/visionforge-gdml/src/commonMain/kotlin/hep/dataforge/vision/gdml/GDMLTransformer.kt +++ b/visionforge-gdml/src/commonMain/kotlin/hep/dataforge/vision/gdml/GDMLTransformer.kt @@ -12,7 +12,7 @@ import hep.dataforge.vision.set import hep.dataforge.vision.solid.* import hep.dataforge.vision.solid.SolidMaterial.Companion.MATERIAL_COLOR_KEY import hep.dataforge.vision.useStyle -import scientifik.gdml.* +import kscience.gdml.* import kotlin.math.cos import kotlin.math.sin import kotlin.random.Random @@ -20,7 +20,7 @@ import kotlin.random.Random private val solidsName = "solids".asName() private val volumesName = "volumes".asName() -class GDMLTransformer internal constructor(val root: GDML) { +public class GDMLTransformer internal constructor(val root: GDML) { //private val materialCache = HashMap() private val random = Random(222) diff --git a/visionforge-gdml/src/commonMain/kotlin/hep/dataforge/vision/gdml/units.kt b/visionforge-gdml/src/commonMain/kotlin/hep/dataforge/vision/gdml/units.kt deleted file mode 100644 index 3e5783ef..00000000 --- a/visionforge-gdml/src/commonMain/kotlin/hep/dataforge/vision/gdml/units.kt +++ /dev/null @@ -1,70 +0,0 @@ -package hep.dataforge.vision.gdml - -import scientifik.gdml.AUnit -import scientifik.gdml.GDMLPosition -import scientifik.gdml.GDMLRotation -import scientifik.gdml.GDMLSolid - -enum class LUnit(val value: Float) { - MM(1f), - CM(10f), - M(1000f) -} - -fun GDMLPosition.unit(): LUnit = LUnit.valueOf(unit.toUpperCase()) - -fun GDMLPosition.x(unit: LUnit): Float = if (unit.name == this.unit) { - x.toFloat() -} else { - x.toFloat() / unit.value * unit().value -} - -fun GDMLPosition.y(unit: LUnit): Float = if (unit.name == this.unit) { - y.toFloat() -} else { - y.toFloat() / unit.value * unit().value -} - -fun GDMLPosition.z(unit: LUnit): Float = if (unit.name == this.unit) { - z.toFloat() -} else { - z.toFloat() / unit.value * unit().value -} - -fun GDMLRotation.unit(): AUnit = AUnit.valueOf(unit.toUpperCase()) - -fun GDMLRotation.x(unit: AUnit = AUnit.RAD): Float = if (unit.name == this.unit) { - x.toFloat() -} else { - x.toFloat() / unit.value * unit().value -} - -fun GDMLRotation.y(unit: AUnit = AUnit.RAD): Float = if (unit.name == this.unit) { - y.toFloat() -} else { - y.toFloat() / unit.value * unit().value -} - -fun GDMLRotation.z(unit: AUnit = AUnit.RAD): Float = if (unit.name == this.unit) { - z.toFloat() -} else { - z.toFloat() / unit.value * unit().value -} - -fun GDMLSolid.lscale(unit: LUnit): Float { - val solidUnit = lunit?.let { LUnit.valueOf(it.toUpperCase()) } ?: return 1f - return if (solidUnit == unit) { - 1f - } else { - solidUnit.value / unit.value - } -} - -fun GDMLSolid.ascale(unit: AUnit = AUnit.RAD): Float { - val solidUnit = aunit?.let { AUnit.valueOf(it.toUpperCase()) } ?: return 1f - return if (solidUnit == unit) { - 1f - } else { - solidUnit.value / unit.value - } -} \ No newline at end of file diff --git a/visionforge-gdml/src/jvmMain/kotlin/hep/dataforge/vision/gdml/gdmlJVM.kt b/visionforge-gdml/src/jvmMain/kotlin/hep/dataforge/vision/gdml/gdmlJVM.kt index 1718cc74..ab58deb9 100644 --- a/visionforge-gdml/src/jvmMain/kotlin/hep/dataforge/vision/gdml/gdmlJVM.kt +++ b/visionforge-gdml/src/jvmMain/kotlin/hep/dataforge/vision/gdml/gdmlJVM.kt @@ -2,7 +2,7 @@ package hep.dataforge.vision.gdml import hep.dataforge.vision.solid.SolidGroup import nl.adaptivity.xmlutil.StAXReader -import scientifik.gdml.GDML +import kscience.gdml.GDML import java.nio.file.Files import java.nio.file.Path import java.util.concurrent.atomic.AtomicInteger diff --git a/visionforge-gdml/src/jvmTest/kotlin/hep/dataforge/vision/gdml/TestConvertor.kt b/visionforge-gdml/src/jvmTest/kotlin/hep/dataforge/vision/gdml/TestConvertor.kt index 287553a1..cf9fb7b4 100644 --- a/visionforge-gdml/src/jvmTest/kotlin/hep/dataforge/vision/gdml/TestConvertor.kt +++ b/visionforge-gdml/src/jvmTest/kotlin/hep/dataforge/vision/gdml/TestConvertor.kt @@ -1,9 +1,9 @@ package hep.dataforge.vision.gdml -import hep.dataforge.vision.solid.stringify +import hep.dataforge.vision.solid.encodeToString import nl.adaptivity.xmlutil.StAXReader import org.junit.jupiter.api.Test -import scientifik.gdml.GDML +import kscience.gdml.GDML class TestConvertor { @@ -13,7 +13,7 @@ class TestConvertor { val xmlReader = StAXReader(stream, "UTF-8") val xml = GDML.format.parse(GDML.serializer(), xmlReader) val vision = xml.toVision() - println(vision.stringify()) + println(vision.encodeToString()) } @Test @@ -33,6 +33,6 @@ class TestConvertor { val xmlReader = StAXReader(stream, "UTF-8") val xml = GDML.format.parse(GDML.serializer(), xmlReader) val visual = xml.toVision() - println(visual.stringify()) + println(visual.encodeToString()) } } \ No newline at end of file diff --git a/visionforge-gdml/src/jvmTest/kotlin/hep/dataforge/vision/gdml/bmanStatistics.kt b/visionforge-gdml/src/jvmTest/kotlin/hep/dataforge/vision/gdml/bmanStatistics.kt index d737d2ae..87b93093 100644 --- a/visionforge-gdml/src/jvmTest/kotlin/hep/dataforge/vision/gdml/bmanStatistics.kt +++ b/visionforge-gdml/src/jvmTest/kotlin/hep/dataforge/vision/gdml/bmanStatistics.kt @@ -8,7 +8,7 @@ import hep.dataforge.vision.visitor.flowStatistics import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext import nl.adaptivity.xmlutil.StAXReader -import scientifik.gdml.GDML +import kscience.gdml.GDML import java.io.File import kotlin.reflect.KClass diff --git a/visionforge-solid/build.gradle.kts b/visionforge-solid/build.gradle.kts index 722cd2f3..7f08e038 100644 --- a/visionforge-solid/build.gradle.kts +++ b/visionforge-solid/build.gradle.kts @@ -1,15 +1,14 @@ -import scientifik.useSerialization +import ru.mipt.npm.gradle.KScienceVersions.coroutinesVersion plugins { - id("scientifik.mpp") + id("ru.mipt.npm.mpp") } -useSerialization() +kscience { + useSerialization() +} kotlin { - js { - useCommonJs() - } sourceSets { commonMain { @@ -22,7 +21,7 @@ kotlin { api("org.fxyz3d:fxyz3d:0.5.2") { exclude(module = "slf4j-simple") } - api("org.jetbrains.kotlinx:kotlinx-coroutines-javafx:${Scientifik.coroutinesVersion}") + api("org.jetbrains.kotlinx:kotlinx-coroutines-javafx:${coroutinesVersion}") implementation("eu.mihosoft.vrl.jcsg:jcsg:0.5.7") { exclude(module = "slf4j-simple") } @@ -37,4 +36,4 @@ kotlin { } } } -} +} \ No newline at end of file diff --git a/visionforge-solid/src/commonMain/kotlin/hep/dataforge/vision/solid/Box.kt b/visionforge-solid/src/commonMain/kotlin/hep/dataforge/vision/solid/Box.kt index 1f05d4ef..5bd6aef5 100644 --- a/visionforge-solid/src/commonMain/kotlin/hep/dataforge/vision/solid/Box.kt +++ b/visionforge-solid/src/commonMain/kotlin/hep/dataforge/vision/solid/Box.kt @@ -5,6 +5,7 @@ package hep.dataforge.vision.solid import hep.dataforge.meta.Config import hep.dataforge.vision.AbstractVision import hep.dataforge.vision.MutableVisionGroup +import hep.dataforge.vision.VisionContainerBuilder import hep.dataforge.vision.set import hep.dataforge.vision.solid.Solid.Companion.solidEquals import kotlinx.serialization.SerialName @@ -13,10 +14,10 @@ import kotlinx.serialization.UseSerializers @Serializable @SerialName("solid.box") -class Box( - val xSize: Float, - val ySize: Float, - val zSize: Float +public class Box( + public val xSize: Float, + public val ySize: Float, + public val zSize: Float ) : AbstractVision(), GeometrySolid { override var position: Point3D? = null @@ -67,15 +68,15 @@ class Box( } - companion object { + public companion object { } } -inline fun MutableVisionGroup.box( +public inline fun VisionContainerBuilder.box( xSize: Number, ySize: Number, zSize: Number, name: String = "", action: Box.() -> Unit = {} -) = Box(xSize.toFloat(), ySize.toFloat(), zSize.toFloat()).apply(action).also { set(name, it) } \ No newline at end of file +): Box = Box(xSize.toFloat(), ySize.toFloat(), zSize.toFloat()).apply(action).also { set(name, it) } \ No newline at end of file diff --git a/visionforge-solid/src/commonMain/kotlin/hep/dataforge/vision/solid/Composite.kt b/visionforge-solid/src/commonMain/kotlin/hep/dataforge/vision/solid/Composite.kt index d2049226..06da6e07 100644 --- a/visionforge-solid/src/commonMain/kotlin/hep/dataforge/vision/solid/Composite.kt +++ b/visionforge-solid/src/commonMain/kotlin/hep/dataforge/vision/solid/Composite.kt @@ -10,7 +10,7 @@ import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable import kotlinx.serialization.UseSerializers -enum class CompositeType { +public enum class CompositeType { UNION, INTERSECT, SUBTRACT @@ -18,10 +18,10 @@ enum class CompositeType { @Serializable @SerialName("solid.composite") -class Composite( - val compositeType: CompositeType, - val first: Solid, - val second: Solid +public class Composite( + public val compositeType: CompositeType, + public val first: Solid, + public val second: Solid ) : AbstractVision(), Solid, VisionGroup { init { @@ -42,7 +42,7 @@ class Composite( get() = null } -inline fun MutableVisionGroup.composite( +public inline fun MutableVisionGroup.composite( type: CompositeType, name: String = "", builder: SolidGroup.() -> Unit @@ -67,11 +67,11 @@ inline fun MutableVisionGroup.composite( } } -inline fun MutableVisionGroup.union(name: String = "", builder: SolidGroup.() -> Unit) = +public inline fun MutableVisionGroup.union(name: String = "", builder: SolidGroup.() -> Unit): Composite = composite(CompositeType.UNION, name, builder = builder) -inline fun MutableVisionGroup.subtract(name: String = "", builder: SolidGroup.() -> Unit) = +public inline fun MutableVisionGroup.subtract(name: String = "", builder: SolidGroup.() -> Unit): Composite = composite(CompositeType.SUBTRACT, name, builder = builder) -inline fun MutableVisionGroup.intersect(name: String = "", builder: SolidGroup.() -> Unit) = +public inline fun MutableVisionGroup.intersect(name: String = "", builder: SolidGroup.() -> Unit): Composite = composite(CompositeType.INTERSECT, name, builder = builder) \ No newline at end of file diff --git a/visionforge-solid/src/commonMain/kotlin/hep/dataforge/vision/solid/ConeSegment.kt b/visionforge-solid/src/commonMain/kotlin/hep/dataforge/vision/solid/ConeSegment.kt index 805151c9..428e6271 100644 --- a/visionforge-solid/src/commonMain/kotlin/hep/dataforge/vision/solid/ConeSegment.kt +++ b/visionforge-solid/src/commonMain/kotlin/hep/dataforge/vision/solid/ConeSegment.kt @@ -5,6 +5,7 @@ package hep.dataforge.vision.solid import hep.dataforge.meta.Config import hep.dataforge.vision.AbstractVision import hep.dataforge.vision.MutableVisionGroup +import hep.dataforge.vision.VisionContainerBuilder import hep.dataforge.vision.set import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable @@ -17,12 +18,12 @@ import kotlin.math.sin */ @Serializable @SerialName("solid.cone") -class ConeSegment( - var radius: Float, - var height: Float, - var upperRadius: Float, - var startAngle: Float = 0f, - var angle: Float = PI2 +public class ConeSegment( + public var radius: Float, + public var height: Float, + public var upperRadius: Float, + public var startAngle: Float = 0f, + public var angle: Float = PI2 ) : AbstractVision(), GeometrySolid { override var properties: Config? = null @@ -75,7 +76,7 @@ class ConeSegment( } -inline fun MutableVisionGroup.cylinder( +public inline fun VisionContainerBuilder.cylinder( r: Number, height: Number, name: String = "", @@ -87,7 +88,7 @@ inline fun MutableVisionGroup.cylinder( ).apply(block).also { set(name, it) } -inline fun MutableVisionGroup.cone( +public inline fun VisionContainerBuilder.cone( bottomRadius: Number, height: Number, upperRadius: Number = 0.0, diff --git a/visionforge-solid/src/commonMain/kotlin/hep/dataforge/vision/solid/Convex.kt b/visionforge-solid/src/commonMain/kotlin/hep/dataforge/vision/solid/Convex.kt index ad17c532..fd2b0389 100644 --- a/visionforge-solid/src/commonMain/kotlin/hep/dataforge/vision/solid/Convex.kt +++ b/visionforge-solid/src/commonMain/kotlin/hep/dataforge/vision/solid/Convex.kt @@ -5,6 +5,7 @@ package hep.dataforge.vision.solid import hep.dataforge.meta.Config import hep.dataforge.vision.AbstractVision import hep.dataforge.vision.MutableVisionGroup +import hep.dataforge.vision.VisionContainerBuilder import hep.dataforge.vision.set import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable @@ -12,7 +13,7 @@ import kotlinx.serialization.UseSerializers @Serializable @SerialName("solid.convex") -class Convex(val points: List) : AbstractVision(), Solid { +public class Convex(public val points: List) : AbstractVision(), Solid { override var properties: Config? = null @@ -23,17 +24,17 @@ class Convex(val points: List) : AbstractVision(), Solid { } -inline fun MutableVisionGroup.convex(name: String = "", action: ConvexBuilder.() -> Unit = {}) = +public inline fun VisionContainerBuilder.convex(name: String = "", action: ConvexBuilder.() -> Unit = {}): Convex = ConvexBuilder().apply(action).build().also { set(name, it) } -class ConvexBuilder { +public class ConvexBuilder { private val points = ArrayList() - fun point(x: Number, y: Number, z: Number) { + public fun point(x: Number, y: Number, z: Number) { points.add(Point3D(x, y, z)) } - fun build(): Convex { + public fun build(): Convex { return Convex(points) } } \ No newline at end of file diff --git a/visionforge-solid/src/commonMain/kotlin/hep/dataforge/vision/solid/Extruded.kt b/visionforge-solid/src/commonMain/kotlin/hep/dataforge/vision/solid/Extruded.kt index e7f92a57..8ca27740 100644 --- a/visionforge-solid/src/commonMain/kotlin/hep/dataforge/vision/solid/Extruded.kt +++ b/visionforge-solid/src/commonMain/kotlin/hep/dataforge/vision/solid/Extruded.kt @@ -4,6 +4,7 @@ package hep.dataforge.vision.solid import hep.dataforge.meta.Config import hep.dataforge.vision.AbstractVision import hep.dataforge.vision.MutableVisionGroup +import hep.dataforge.vision.VisionContainerBuilder import hep.dataforge.vision.set import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable @@ -13,21 +14,21 @@ import kotlin.math.cos import kotlin.math.sin -typealias Shape2D = List +public typealias Shape2D = List @Serializable -class Shape2DBuilder(private val points: MutableList = ArrayList()) { +public class Shape2DBuilder(private val points: MutableList = ArrayList()) { - fun point(x: Number, y: Number) { + public fun point(x: Number, y: Number) { points.add(Point2D(x, y)) } - infix fun Number.to(y: Number) = point(this, y) + public infix fun Number.to(y: Number): Unit = point(this, y) - fun build(): Shape2D = points + public fun build(): Shape2D = points } -fun Shape2DBuilder.polygon(vertices: Int, radius: Number) { +public fun Shape2DBuilder.polygon(vertices: Int, radius: Number) { require(vertices > 2) { "Polygon must have more than 2 vertices" } val angle = 2 * PI / vertices for (i in 0 until vertices) { @@ -36,13 +37,13 @@ fun Shape2DBuilder.polygon(vertices: Int, radius: Number) { } @Serializable -data class Layer(var x: Float, var y: Float, var z: Float, var scale: Float) +public data class Layer(var x: Float, var y: Float, var z: Float, var scale: Float) @Serializable @SerialName("solid.extrude") -class Extruded( - var shape: List = ArrayList(), - var layers: MutableList = ArrayList() +public class Extruded( + public var shape: List = ArrayList(), + public var layers: MutableList = ArrayList() ) : AbstractVision(), GeometrySolid { override var properties: Config? = null @@ -51,12 +52,12 @@ class Extruded( override var rotation: Point3D? = null override var scale: Point3D? = null - fun shape(block: Shape2DBuilder.() -> Unit) { + public fun shape(block: Shape2DBuilder.() -> Unit) { this.shape = Shape2DBuilder().apply(block).build() //TODO send invalidation signal } - fun layer(z: Number, x: Number = 0.0, y: Number = 0.0, scale: Number = 1.0) { + public fun layer(z: Number, x: Number = 0.0, y: Number = 0.0, scale: Number = 1.0) { layers.add(Layer(x.toFloat(), y.toFloat(), z.toFloat(), scale.toFloat())) //TODO send invalidation signal } @@ -107,10 +108,10 @@ class Extruded( geometryBuilder.cap(layers.last()) } - companion object { - const val TYPE = "geometry.3d.extruded" + public companion object { + public const val TYPE: String = "solid.extruded" } } -fun MutableVisionGroup.extrude(name: String = "", action: Extruded.() -> Unit = {}) = +public fun VisionContainerBuilder.extrude(name: String = "", action: Extruded.() -> Unit = {}): Extruded = Extruded().apply(action).also { set(name, it) } \ No newline at end of file diff --git a/visionforge-solid/src/commonMain/kotlin/hep/dataforge/vision/solid/GeometryBuilder.kt b/visionforge-solid/src/commonMain/kotlin/hep/dataforge/vision/solid/GeometryBuilder.kt index b813da89..5d06ea2a 100644 --- a/visionforge-solid/src/commonMain/kotlin/hep/dataforge/vision/solid/GeometryBuilder.kt +++ b/visionforge-solid/src/commonMain/kotlin/hep/dataforge/vision/solid/GeometryBuilder.kt @@ -5,7 +5,7 @@ import hep.dataforge.meta.Meta /** * @param T the type of resulting geometry */ -interface GeometryBuilder { +public interface GeometryBuilder { /** * Add a face to 3D model. If one of the vertices is not present in the current geometry model list of vertices, * it is added automatically. @@ -13,12 +13,12 @@ interface GeometryBuilder { * @param normal optional external normal to the face * @param meta optional additional platform-specific parameters like color or texture index */ - fun face(vertex1: Point3D, vertex2: Point3D, vertex3: Point3D, normal: Point3D? = null, meta: Meta = Meta.EMPTY) + public fun face(vertex1: Point3D, vertex2: Point3D, vertex3: Point3D, normal: Point3D? = null, meta: Meta = Meta.EMPTY) - fun build(): T + public fun build(): T } -fun GeometryBuilder<*>.face4( +public fun GeometryBuilder<*>.face4( vertex1: Point3D, vertex2: Point3D, vertex3: Point3D, @@ -33,11 +33,11 @@ fun GeometryBuilder<*>.face4( /** * [GeometrySolid] is a [Solid] that can represent its own geometry as a set of polygons. */ -interface GeometrySolid : Solid { - fun toGeometry(geometryBuilder: GeometryBuilder) +public interface GeometrySolid : Solid { + public fun toGeometry(geometryBuilder: GeometryBuilder) } -fun GeometryBuilder.cap(shape: List, normal: Point3D? = null) { +public fun GeometryBuilder.cap(shape: List, normal: Point3D? = null) { //FIXME won't work for non-convex shapes val center = Point3D( shape.map { it.x }.average(), diff --git a/visionforge-solid/src/commonMain/kotlin/hep/dataforge/vision/solid/PolyLine.kt b/visionforge-solid/src/commonMain/kotlin/hep/dataforge/vision/solid/PolyLine.kt index 280e6b9b..67e22080 100644 --- a/visionforge-solid/src/commonMain/kotlin/hep/dataforge/vision/solid/PolyLine.kt +++ b/visionforge-solid/src/commonMain/kotlin/hep/dataforge/vision/solid/PolyLine.kt @@ -4,10 +4,12 @@ package hep.dataforge.vision.solid import hep.dataforge.meta.Config import hep.dataforge.meta.number +import hep.dataforge.names.Name import hep.dataforge.names.asName import hep.dataforge.names.plus import hep.dataforge.vision.AbstractVision import hep.dataforge.vision.MutableVisionGroup +import hep.dataforge.vision.VisionContainerBuilder import hep.dataforge.vision.set import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable @@ -15,7 +17,7 @@ import kotlinx.serialization.UseSerializers @Serializable @SerialName("solid.line") -class PolyLine(var points: List) : AbstractVision(), Solid { +public class PolyLine(public var points: List) : AbstractVision(), Solid { override var properties: Config? = null override var position: Point3D? = null @@ -23,13 +25,13 @@ class PolyLine(var points: List) : AbstractVision(), Solid { override var scale: Point3D? = null //var lineType by string() - var thickness by number(1.0, key = SolidMaterial.MATERIAL_KEY + THICKNESS_KEY) + public var thickness: Number by number(1.0, key = SolidMaterial.MATERIAL_KEY + THICKNESS_KEY) - companion object { - val THICKNESS_KEY = "thickness".asName() + public companion object { + public val THICKNESS_KEY: Name = "thickness".asName() } } -fun MutableVisionGroup.polyline(vararg points: Point3D, name: String = "", action: PolyLine.() -> Unit = {}) = +public fun VisionContainerBuilder.polyline(vararg points: Point3D, name: String = "", action: PolyLine.() -> Unit = {}): PolyLine = PolyLine(points.toList()).apply(action).also { set(name, it) } \ No newline at end of file diff --git a/visionforge-solid/src/commonMain/kotlin/hep/dataforge/vision/solid/Proxy.kt b/visionforge-solid/src/commonMain/kotlin/hep/dataforge/vision/solid/Proxy.kt index bf2369a7..cc56f827 100644 --- a/visionforge-solid/src/commonMain/kotlin/hep/dataforge/vision/solid/Proxy.kt +++ b/visionforge-solid/src/commonMain/kotlin/hep/dataforge/vision/solid/Proxy.kt @@ -12,8 +12,8 @@ import kotlinx.serialization.Transient import kotlinx.serialization.UseSerializers import kotlin.collections.set -abstract class AbstractProxy : AbstractVision(), VisionGroup { - abstract val prototype: Vision +public abstract class AbstractProxy : AbstractVision(), VisionGroup { + public abstract val prototype: Vision override fun getProperty(name: Name, inherit: Boolean): MetaItem<*>? { return if (inherit) { @@ -33,7 +33,7 @@ abstract class AbstractProxy : AbstractVision(), VisionGroup { } override var styles: List - get() = properties[Vision.STYLE_KEY].stringList + prototype.styles + get() = (properties[Vision.STYLE_KEY]?.stringList ?: emptyList()) + prototype.styles set(value) { config[Vision.STYLE_KEY] = value } @@ -53,11 +53,11 @@ abstract class AbstractProxy : AbstractVision(), VisionGroup { */ @Serializable @SerialName("solid.proxy") -class Proxy private constructor( - val templateName: Name +public class Proxy private constructor( + public val templateName: Name ) : AbstractProxy(), Solid { - constructor(parent: SolidGroup, templateName: Name) : this(templateName) { + public constructor(parent: SolidGroup, templateName: Name) : this(templateName) { this.parent = parent } @@ -104,7 +104,7 @@ class Proxy private constructor( * A ProxyChild is created temporarily only to interact with properties, it does not store any values * (properties are stored in external cache) and created and destroyed on-demand). */ - inner class ProxyChild(val name: Name) : AbstractProxy() { + public inner class ProxyChild(public val name: Name) : AbstractProxy() { override val prototype: Vision get() = prototypeFor(name) @@ -136,12 +136,15 @@ class Proxy private constructor( } - companion object { - const val PROXY_CHILD_PROPERTY_PREFIX = "@child" + public companion object { + public const val PROXY_CHILD_PROPERTY_PREFIX: String = "@child" } } -val Vision.prototype: Vision +/** + * Get a vision prototype if it is a [Proxy] or vision itself if it is not + */ +public val Vision.prototype: Vision get() = when (this) { is AbstractProxy -> prototype else -> this @@ -150,7 +153,7 @@ val Vision.prototype: Vision /** * Create ref for existing prototype */ -fun SolidGroup.ref( +public fun SolidGroup.ref( templateName: Name, name: String = "" ): Proxy = Proxy(this, templateName).also { set(name, it) } @@ -158,7 +161,7 @@ fun SolidGroup.ref( /** * Add new proxy wrapping given object and automatically adding it to the prototypes */ -fun SolidGroup.proxy( +public fun SolidGroup.proxy( name: String, obj: Solid, templateName: Name = name.toName() @@ -173,12 +176,3 @@ fun SolidGroup.proxy( } return ref(templateName, name) } - -fun SolidGroup.proxyGroup( - name: String, - templateName: Name = name.toName(), - block: MutableVisionGroup.() -> Unit -): Proxy { - val group = SolidGroup().apply(block) - return proxy(name, group, templateName) -} diff --git a/visionforge-solid/src/commonMain/kotlin/hep/dataforge/vision/solid/Solid.kt b/visionforge-solid/src/commonMain/kotlin/hep/dataforge/vision/solid/Solid.kt index 721d38ee..fce83d6d 100644 --- a/visionforge-solid/src/commonMain/kotlin/hep/dataforge/vision/solid/Solid.kt +++ b/visionforge-solid/src/commonMain/kotlin/hep/dataforge/vision/solid/Solid.kt @@ -4,65 +4,63 @@ package hep.dataforge.vision.solid import hep.dataforge.meta.* import hep.dataforge.meta.descriptors.NodeDescriptor +import hep.dataforge.names.Name import hep.dataforge.names.asName import hep.dataforge.names.plus import hep.dataforge.output.Renderer import hep.dataforge.values.ValueType import hep.dataforge.values.asValue import hep.dataforge.vision.Vision +import hep.dataforge.vision.Vision.Companion.VISIBLE_KEY import hep.dataforge.vision.enum 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.LAYER_KEY -import hep.dataforge.vision.solid.Solid.Companion.VISIBLE_KEY import kotlinx.serialization.UseSerializers /** * Interface for 3-dimensional [Vision] */ -interface Solid : Vision { - var position: Point3D? - var rotation: Point3D? - var scale: Point3D? +public interface Solid : Vision { + public var position: Point3D? + public var rotation: Point3D? + public var scale: Point3D? override val descriptor: NodeDescriptor? get() = Companion.descriptor - companion object { - - val VISIBLE_KEY = "visible".asName() - + public companion object { // val SELECTED_KEY = "selected".asName() - val DETAIL_KEY = "detail".asName() - val LAYER_KEY = "layer".asName() - val IGNORE_KEY = "ignore".asName() + public val DETAIL_KEY: Name = "detail".asName() + public val LAYER_KEY: Name = "layer".asName() + public val IGNORE_KEY: Name = "ignore".asName() - val GEOMETRY_KEY = "geometry".asName() + public val GEOMETRY_KEY: Name = "geometry".asName() - val X_KEY = "x".asName() - val Y_KEY = "y".asName() - val Z_KEY = "z".asName() + public val X_KEY: Name = "x".asName() + public val Y_KEY: Name = "y".asName() + public val Z_KEY: Name = "z".asName() - val POSITION_KEY = "pos".asName() + public val POSITION_KEY: Name = "pos".asName() - val X_POSITION_KEY = POSITION_KEY + X_KEY - val Y_POSITION_KEY = POSITION_KEY + Y_KEY - val Z_POSITION_KEY = POSITION_KEY + Z_KEY + public val X_POSITION_KEY: Name = POSITION_KEY + X_KEY + public val Y_POSITION_KEY: Name = POSITION_KEY + Y_KEY + public val Z_POSITION_KEY: Name = POSITION_KEY + Z_KEY - val ROTATION = "rotation".asName() + public val ROTATION: Name = "rotation".asName() - val X_ROTATION_KEY = ROTATION + X_KEY - val Y_ROTATION_KEY = ROTATION + Y_KEY - val Z_ROTATION_KEY = ROTATION + Z_KEY + public val X_ROTATION_KEY: Name = ROTATION + X_KEY + public val Y_ROTATION_KEY: Name = ROTATION + Y_KEY + public val Z_ROTATION_KEY: Name = ROTATION + Z_KEY - val ROTATION_ORDER_KEY = ROTATION + "order" + public val ROTATION_ORDER_KEY: Name = ROTATION + "order" - val SCALE_KEY = "scale".asName() + public val SCALE_KEY: Name = "scale".asName() - val X_SCALE_KEY = SCALE_KEY + X_KEY - val Y_SCALE_KEY = SCALE_KEY + Y_KEY - val Z_SCALE_KEY = SCALE_KEY + Z_KEY + public val X_SCALE_KEY: Name = SCALE_KEY + X_KEY + public val Y_SCALE_KEY: Name = SCALE_KEY + Y_KEY + public val Z_SCALE_KEY: Name = SCALE_KEY + Z_KEY - val descriptor by lazy { + public val descriptor: NodeDescriptor by lazy { NodeDescriptor { value(VISIBLE_KEY) { type(ValueType.BOOLEAN) @@ -100,20 +98,20 @@ interface Solid : Vision { } /** - * Count number of layers to the top object. Return 1 if this is top layer + * Get the layer number this solid belongs to. Return 0 if layer is not defined. */ -var Solid.layer: Int +public var Solid.layer: Int get() = properties?.getItem(LAYER_KEY).int ?: 0 set(value) { config[LAYER_KEY] = value.asValue() } -fun Renderer.render(meta: Meta = Meta.EMPTY, action: SolidGroup.() -> Unit) = +public fun Renderer.render(meta: Meta = Meta.EMPTY, action: SolidGroup.() -> Unit): Unit = render(SolidGroup().apply(action), meta) // Common properties -enum class RotationOrder { +public enum class RotationOrder { XYZ, YZX, ZXY, @@ -125,7 +123,7 @@ enum class RotationOrder { /** * Rotation order */ -var Solid.rotationOrder: RotationOrder +public var Solid.rotationOrder: RotationOrder get() = getItem(Solid.ROTATION_ORDER_KEY).enum() ?: RotationOrder.XYZ set(value) = setItem(Solid.ROTATION_ORDER_KEY, value.name.asValue()) @@ -133,19 +131,15 @@ var Solid.rotationOrder: RotationOrder /** * Preferred number of polygons for displaying the object. If not defined, uses shape or renderer default. Not inherited */ -var Solid.detail: Int? +public var Solid.detail: Int? get() = getProperty(DETAIL_KEY, false).int set(value) = setItem(DETAIL_KEY, value?.asValue()) -var Vision.visible: Boolean? - get() = getItem(VISIBLE_KEY).boolean - set(value) = setItem(VISIBLE_KEY, value?.asValue()) - /** * If this property is true, the object will be ignored on render. * Property is not inherited. */ -var Vision.ignore: Boolean? +public var Vision.ignore: Boolean? get() = getProperty(IGNORE_KEY, false).boolean set(value) = setItem(IGNORE_KEY, value?.asValue()) @@ -156,21 +150,21 @@ var Vision.ignore: Boolean? private fun Solid.position(): Point3D = position ?: Point3D(0.0, 0.0, 0.0).also { position = it } -var Solid.x: Number +public var Solid.x: Number get() = position?.x ?: 0f set(value) { position().x = value.toDouble() propertyChanged(Solid.X_POSITION_KEY) } -var Solid.y: Number +public var Solid.y: Number get() = position?.y ?: 0f set(value) { position().y = value.toDouble() propertyChanged(Solid.Y_POSITION_KEY) } -var Solid.z: Number +public var Solid.z: Number get() = position?.z ?: 0f set(value) { position().z = value.toDouble() @@ -180,21 +174,21 @@ var Solid.z: Number private fun Solid.rotation(): Point3D = rotation ?: Point3D(0.0, 0.0, 0.0).also { rotation = it } -var Solid.rotationX: Number +public var Solid.rotationX: Number get() = rotation?.x ?: 0f set(value) { rotation().x = value.toDouble() propertyChanged(Solid.X_ROTATION_KEY) } -var Solid.rotationY: Number +public var Solid.rotationY: Number get() = rotation?.y ?: 0f set(value) { rotation().y = value.toDouble() propertyChanged(Solid.Y_ROTATION_KEY) } -var Solid.rotationZ: Number +public var Solid.rotationZ: Number get() = rotation?.z ?: 0f set(value) { rotation().z = value.toDouble() @@ -204,21 +198,21 @@ var Solid.rotationZ: Number private fun Solid.scale(): Point3D = scale ?: Point3D(1.0, 1.0, 1.0).also { scale = it } -var Solid.scaleX: Number +public var Solid.scaleX: Number get() = scale?.x ?: 1f set(value) { scale().x = value.toDouble() propertyChanged(Solid.X_SCALE_KEY) } -var Solid.scaleY: Number +public var Solid.scaleY: Number get() = scale?.y ?: 1f set(value) { scale().y = value.toDouble() propertyChanged(Solid.Y_SCALE_KEY) } -var Solid.scaleZ: Number +public var Solid.scaleZ: Number get() = scale?.z ?: 1f set(value) { scale().z = value.toDouble() diff --git a/visionforge-solid/src/commonMain/kotlin/hep/dataforge/vision/solid/SolidGroup.kt b/visionforge-solid/src/commonMain/kotlin/hep/dataforge/vision/solid/SolidGroup.kt index 83e2deff..1e2dd7a4 100644 --- a/visionforge-solid/src/commonMain/kotlin/hep/dataforge/vision/solid/SolidGroup.kt +++ b/visionforge-solid/src/commonMain/kotlin/hep/dataforge/vision/solid/SolidGroup.kt @@ -15,9 +15,9 @@ import kotlinx.serialization.Serializable import kotlinx.serialization.UseSerializers import kotlin.collections.set -interface PrototypeHolder { - val parent: VisionGroup? - val prototypes: MutableVisionGroup? +public interface PrototypeHolder { + public val parent: VisionGroup? + public val prototypes: MutableVisionGroup? } /** @@ -25,7 +25,7 @@ interface PrototypeHolder { */ @Serializable @SerialName("group.solid") -class SolidGroup : AbstractVisionGroup(), Solid, PrototypeHolder { +public class SolidGroup : AbstractVisionGroup(), Solid, PrototypeHolder { override var styleSheet: StyleSheet? = null @@ -39,7 +39,7 @@ class SolidGroup : AbstractVisionGroup(), Solid, PrototypeHolder { /** * Create or edit prototype node as a group */ - fun prototypes(builder: MutableVisionGroup.() -> Unit): Unit { + public fun prototypes(builder: MutableVisionGroup.() -> Unit): Unit { (prototypes ?: Prototypes().also { prototypes = it attach(it) @@ -79,33 +79,33 @@ class SolidGroup : AbstractVisionGroup(), Solid, PrototypeHolder { override fun createGroup(): SolidGroup = SolidGroup() - companion object { + public companion object { // val PROTOTYPES_KEY = NameToken("@prototypes") @OptIn(DFExperimental::class) - fun parseJson(json: String): SolidGroup = - SolidManager.jsonForSolids.parse(serializer(), json).also { it.attachChildren() } + public fun decodeFromString(json: String): SolidGroup = + SolidManager.jsonForSolids.decodeFromString(serializer(), json).also { it.attachChildren() } } } @Suppress("FunctionName") -fun SolidGroup(block: SolidGroup.() -> Unit): SolidGroup { +public fun SolidGroup(block: SolidGroup.() -> Unit): SolidGroup { return SolidGroup().apply(block) } /** * Ger a prototype redirecting the request to the parent if prototype is not found */ -tailrec fun PrototypeHolder.getPrototype(name: Name): Solid? = +public tailrec fun PrototypeHolder.getPrototype(name: Name): Solid? = prototypes?.get(name) as? Solid ?: (parent as? PrototypeHolder)?.getPrototype(name) -fun MutableVisionGroup.group(name: Name = Name.EMPTY, action: SolidGroup.() -> Unit = {}): SolidGroup = +public fun MutableVisionGroup.group(name: Name = Name.EMPTY, action: SolidGroup.() -> Unit = {}): SolidGroup = SolidGroup().apply(action).also { set(name, it) } /** * Define a group with given [name], attach it to this parent and return it. */ -fun MutableVisionGroup.group(name: String, action: SolidGroup.() -> Unit = {}): SolidGroup = +public fun MutableVisionGroup.group(name: String, action: SolidGroup.() -> Unit = {}): SolidGroup = SolidGroup().apply(action).also { set(name, it) } /** diff --git a/visionforge-solid/src/commonMain/kotlin/hep/dataforge/vision/solid/SolidLabel.kt b/visionforge-solid/src/commonMain/kotlin/hep/dataforge/vision/solid/SolidLabel.kt index c740f778..c7f459a5 100644 --- a/visionforge-solid/src/commonMain/kotlin/hep/dataforge/vision/solid/SolidLabel.kt +++ b/visionforge-solid/src/commonMain/kotlin/hep/dataforge/vision/solid/SolidLabel.kt @@ -5,6 +5,7 @@ package hep.dataforge.vision.solid import hep.dataforge.meta.Config import hep.dataforge.vision.AbstractVision import hep.dataforge.vision.MutableVisionGroup +import hep.dataforge.vision.VisionContainerBuilder import hep.dataforge.vision.set import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable @@ -12,7 +13,7 @@ import kotlinx.serialization.UseSerializers @Serializable @SerialName("solid.label") -class SolidLabel(var text: String, var fontSize: Double, var fontFamily: String) : AbstractVision(), Solid { +public class SolidLabel(public var text: String, public var fontSize: Double, public var fontFamily: String) : AbstractVision(), Solid { override var properties: Config? = null override var position: Point3D? = null @@ -21,11 +22,10 @@ class SolidLabel(var text: String, var fontSize: Double, var fontFamily: String) } -fun MutableVisionGroup.label( +public fun VisionContainerBuilder.label( text: String, fontSize: Number = 20, fontFamily: String = "Arial", name: String = "", - action: SolidLabel.() -> Unit = {} -) = - SolidLabel(text, fontSize.toDouble(), fontFamily).apply(action).also { set(name, it) } \ No newline at end of file + action: SolidLabel.() -> Unit = {}, +): SolidLabel = SolidLabel(text, fontSize.toDouble(), fontFamily).apply(action).also { set(name, it) } \ No newline at end of file diff --git a/visionforge-solid/src/commonMain/kotlin/hep/dataforge/vision/solid/SolidManager.kt b/visionforge-solid/src/commonMain/kotlin/hep/dataforge/vision/solid/SolidManager.kt index 36a46425..5cc3948c 100644 --- a/visionforge-solid/src/commonMain/kotlin/hep/dataforge/vision/solid/SolidManager.kt +++ b/visionforge-solid/src/commonMain/kotlin/hep/dataforge/vision/solid/SolidManager.kt @@ -12,20 +12,17 @@ import hep.dataforge.vision.Vision import hep.dataforge.vision.VisionForm import hep.dataforge.vision.VisionManager import hep.dataforge.vision.VisionManager.Companion.VISION_SERIAL_MODULE_TARGET +import kotlinx.serialization.DeserializationStrategy +import kotlinx.serialization.ExperimentalSerializationApi import kotlinx.serialization.KSerializer -import kotlinx.serialization.UnstableDefault import kotlinx.serialization.json.Json -import kotlinx.serialization.json.JsonConfiguration -import kotlinx.serialization.modules.SerialModule -import kotlinx.serialization.modules.SerialModuleCollector -import kotlinx.serialization.modules.SerializersModule -import kotlinx.serialization.modules.contextual +import kotlinx.serialization.modules.* import kotlin.reflect.KClass @DFExperimental -private class SolidForm( +private class SolidForm( override val type: KClass, - override val serializer: KSerializer + override val serializer: KSerializer, ) : VisionForm { private fun Solid.update(meta: Meta) { @@ -46,12 +43,12 @@ private class SolidForm( } } +@OptIn(ExperimentalSerializationApi::class) @DFExperimental -@OptIn(UnstableDefault::class) -private fun SerialModule.extractFactories(): List> { +private fun SerializersModule.extractFactories(): List> { val list = ArrayList>() - val collector = object : SerialModuleCollector { + val collector = object : SerializersModuleCollector { override fun contextual(kClass: KClass, serializer: KSerializer) { //Do nothing } @@ -59,7 +56,7 @@ private fun SerialModule.extractFactories(): List> { override fun polymorphic( baseClass: KClass, actualClass: KClass, - actualSerializer: KSerializer + actualSerializer: KSerializer, ) { if (baseClass == Vision::class) { @Suppress("UNCHECKED_CAST") val factory = SolidForm( @@ -70,34 +67,41 @@ private fun SerialModule.extractFactories(): List> { } } + override fun polymorphicDefault( + baseClass: KClass, + defaultSerializerProvider: (className: String?) -> DeserializationStrategy?, + ) { + TODO("Not yet implemented") + } + } dumpTo(collector) return list } @DFExperimental -class SolidManager(meta: Meta) : AbstractPlugin(meta) { +public class SolidManager(meta: Meta) : AbstractPlugin(meta) { - val visionManager by require(VisionManager) + public val visionManager: VisionManager by require(VisionManager) override val tag: PluginTag get() = Companion.tag - override fun provideTop(target: String): Map = when (target) { + override fun content(target: String): Map = when (target) { VisionForm.TYPE -> serialModule.extractFactories().associateBy { it.name } VISION_SERIAL_MODULE_TARGET -> mapOf(tag.name.toName() to serialModule) - else -> super.provideTop(target) + else -> super.content(target) } - companion object : PluginFactory { + public companion object : PluginFactory { override val tag: PluginTag = PluginTag(name = "visual.spatial", group = PluginTag.DATAFORGE_GROUP) override val type: KClass = SolidManager::class override fun invoke(meta: Meta, context: Context): SolidManager = SolidManager(meta) - val serialModule = SerializersModule { + public val serialModule: SerializersModule = SerializersModule { contextual(Point3DSerializer) contextual(Point2DSerializer) - polymorphic(Vision::class, Solid::class) { + polymorphic(Vision::class) { subclass(SimpleVisionGroup.serializer()) subclass(SolidGroup.serializer()) subclass(Proxy.serializer()) @@ -112,15 +116,12 @@ class SolidManager(meta: Meta) : AbstractPlugin(meta) { } } - @OptIn(UnstableDefault::class) - val jsonForSolids = Json( - JsonConfiguration( - prettyPrint = true, - useArrayPolymorphism = false, - encodeDefaults = false, - ignoreUnknownKeys = true - ), - context = serialModule - ) + val jsonForSolids = Json { + prettyPrint = true + useArrayPolymorphism = false + encodeDefaults = false + ignoreUnknownKeys = true + serializersModule = this@Companion.serialModule + } } } diff --git a/visionforge-solid/src/commonMain/kotlin/hep/dataforge/vision/solid/SolidMaterial.kt b/visionforge-solid/src/commonMain/kotlin/hep/dataforge/vision/solid/SolidMaterial.kt index d5a29a55..d1a9b121 100644 --- a/visionforge-solid/src/commonMain/kotlin/hep/dataforge/vision/solid/SolidMaterial.kt +++ b/visionforge-solid/src/commonMain/kotlin/hep/dataforge/vision/solid/SolidMaterial.kt @@ -3,6 +3,7 @@ package hep.dataforge.vision.solid import hep.dataforge.meta.* import hep.dataforge.meta.descriptors.NodeDescriptor import hep.dataforge.meta.descriptors.attributes +import hep.dataforge.names.Name import hep.dataforge.names.asName import hep.dataforge.names.plus import hep.dataforge.values.ValueType @@ -13,41 +14,41 @@ import hep.dataforge.vision.solid.SolidMaterial.Companion.MATERIAL_KEY import hep.dataforge.vision.solid.SolidMaterial.Companion.MATERIAL_OPACITY_KEY import hep.dataforge.vision.widgetType -class SolidMaterial : Scheme() { +public class SolidMaterial : Scheme() { /** * Primary web-color for the material */ - var color by string(key = COLOR_KEY) + public var color: String? by string(key = COLOR_KEY) /** * Specular color for phong material */ - var specularColor by string(key = SPECULAR_COLOR_KEY) + public var specularColor: String? by string(key = SPECULAR_COLOR_KEY) /** * Opacity */ - var opacity by float(1f, key = OPACITY_KEY) + public var opacity: Float by float(1f, key = OPACITY_KEY) /** * Replace material by wire frame */ - var wireframe by boolean(false, WIREFRAME_KEY) + public var wireframe: Boolean by boolean(false, WIREFRAME_KEY) - companion object : SchemeSpec(::SolidMaterial) { + public companion object : SchemeSpec(::SolidMaterial) { - val MATERIAL_KEY = "material".asName() + public val MATERIAL_KEY: Name = "material".asName() internal val COLOR_KEY = "color".asName() - val MATERIAL_COLOR_KEY = MATERIAL_KEY + COLOR_KEY + public val MATERIAL_COLOR_KEY: Name = MATERIAL_KEY + COLOR_KEY internal val SPECULAR_COLOR_KEY = "specularColor".asName() - val MATERIAL_SPECULAR_COLOR_KEY = MATERIAL_KEY + SPECULAR_COLOR_KEY + public val MATERIAL_SPECULAR_COLOR_KEY: Name = MATERIAL_KEY + SPECULAR_COLOR_KEY internal val OPACITY_KEY = "opacity".asName() - val MATERIAL_OPACITY_KEY = MATERIAL_KEY + OPACITY_KEY + public val MATERIAL_OPACITY_KEY: Name = MATERIAL_KEY + OPACITY_KEY internal val WIREFRAME_KEY = "wireframe".asName() - val MATERIAL_WIREFRAME_KEY = MATERIAL_KEY + WIREFRAME_KEY + public val MATERIAL_WIREFRAME_KEY: Name = MATERIAL_KEY + WIREFRAME_KEY - val descriptor by lazy { + public val descriptor: NodeDescriptor by lazy { //must be lazy to avoid initialization bug NodeDescriptor { value(COLOR_KEY) { @@ -77,18 +78,18 @@ class SolidMaterial : Scheme() { /** * Set color as web-color */ -fun Solid.color(webColor: String) { +public fun Solid.color(webColor: String) { setItem(MATERIAL_COLOR_KEY, webColor.asValue()) } /** * Set color as integer */ -fun Solid.color(rgb: Int) { +public fun Solid.color(rgb: Int) { setItem(MATERIAL_COLOR_KEY, rgb.asValue()) } -fun Solid.color(r: UByte, g: UByte, b: UByte) = setItem( +public fun Solid.color(r: UByte, g: UByte, b: UByte): Unit = setItem( MATERIAL_COLOR_KEY, Colors.rgbToMeta(r, g, b) ) @@ -96,16 +97,16 @@ fun Solid.color(r: UByte, g: UByte, b: UByte) = setItem( /** * Web colors representation of the color in `#rrggbb` format or HTML name */ -var Solid.color: String? +public var Solid.color: String? get() = getItem(MATERIAL_COLOR_KEY)?.let { Colors.fromMeta(it) } set(value) { setItem(MATERIAL_COLOR_KEY, value?.asValue()) } -val Solid.material: SolidMaterial? +public val Solid.material: SolidMaterial? get() = getItem(MATERIAL_KEY).node?.let { SolidMaterial.wrap(it) } -fun Solid.material(builder: SolidMaterial.() -> Unit) { +public fun Solid.material(builder: SolidMaterial.() -> Unit) { val node = config[MATERIAL_KEY].node if (node != null) { SolidMaterial.update(node, builder) @@ -114,7 +115,7 @@ fun Solid.material(builder: SolidMaterial.() -> Unit) { } } -var Solid.opacity: Double? +public var Solid.opacity: Double? get() = getItem(MATERIAL_OPACITY_KEY).double set(value) { setItem(MATERIAL_OPACITY_KEY, value?.asValue()) diff --git a/visionforge-solid/src/commonMain/kotlin/hep/dataforge/vision/solid/Sphere.kt b/visionforge-solid/src/commonMain/kotlin/hep/dataforge/vision/solid/Sphere.kt index 13cb7fbd..f21dfbc6 100644 --- a/visionforge-solid/src/commonMain/kotlin/hep/dataforge/vision/solid/Sphere.kt +++ b/visionforge-solid/src/commonMain/kotlin/hep/dataforge/vision/solid/Sphere.kt @@ -5,6 +5,7 @@ package hep.dataforge.vision.solid import hep.dataforge.meta.Config import hep.dataforge.vision.AbstractVision import hep.dataforge.vision.MutableVisionGroup +import hep.dataforge.vision.VisionContainerBuilder import hep.dataforge.vision.set import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable @@ -15,12 +16,12 @@ import kotlin.math.sin @Serializable @SerialName("solid.sphere") -class Sphere( - var radius: Float, - var phiStart: Float = 0f, - var phi: Float = PI2, - var thetaStart: Float = 0f, - var theta: Float = PI.toFloat() +public class Sphere( + public var radius: Float, + public var phiStart: Float = 0f, + public var phi: Float = PI2, + public var thetaStart: Float = 0f, + public var theta: Float = PI.toFloat() ) : AbstractVision(), GeometrySolid { override var properties: Config? = null @@ -60,13 +61,13 @@ class Sphere( } } -inline fun MutableVisionGroup.sphere( +public inline fun VisionContainerBuilder.sphere( radius: Number, phi: Number = 2 * PI, theta: Number = PI, name: String = "", action: Sphere.() -> Unit = {} -) = Sphere( +): Sphere = Sphere( radius.toFloat(), phi = phi.toFloat(), theta = theta.toFloat() diff --git a/visionforge-solid/src/commonMain/kotlin/hep/dataforge/vision/solid/Tube.kt b/visionforge-solid/src/commonMain/kotlin/hep/dataforge/vision/solid/Tube.kt index a8b699c5..9bc2add9 100644 --- a/visionforge-solid/src/commonMain/kotlin/hep/dataforge/vision/solid/Tube.kt +++ b/visionforge-solid/src/commonMain/kotlin/hep/dataforge/vision/solid/Tube.kt @@ -5,6 +5,7 @@ package hep.dataforge.vision.solid import hep.dataforge.meta.Config import hep.dataforge.vision.AbstractVision import hep.dataforge.vision.MutableVisionGroup +import hep.dataforge.vision.VisionContainerBuilder import hep.dataforge.vision.set import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable @@ -18,12 +19,12 @@ import kotlin.math.sin */ @Serializable @SerialName("solid.tube") -class Tube( - var radius: Float, - var height: Float, - var innerRadius: Float = 0f, - var startAngle: Float = 0f, - var angle: Float = PI2 +public class Tube( + public var radius: Float, + public var height: Float, + public var innerRadius: Float = 0f, + public var startAngle: Float = 0f, + public var angle: Float = PI2 ) : AbstractVision(), GeometrySolid { override var position: Point3D? = null @@ -129,7 +130,7 @@ class Tube( } -inline fun MutableVisionGroup.tube( +public inline fun VisionContainerBuilder.tube( r: Number, height: Number, innerRadius: Number = 0f, diff --git a/visionforge-solid/src/commonMain/kotlin/hep/dataforge/vision/solid/geometry.kt b/visionforge-solid/src/commonMain/kotlin/hep/dataforge/vision/solid/geometry.kt index 8764bc41..1eb501b0 100644 --- a/visionforge-solid/src/commonMain/kotlin/hep/dataforge/vision/solid/geometry.kt +++ b/visionforge-solid/src/commonMain/kotlin/hep/dataforge/vision/solid/geometry.kt @@ -1,47 +1,48 @@ package hep.dataforge.vision.solid import hep.dataforge.meta.Meta +import hep.dataforge.meta.MetaBuilder import hep.dataforge.meta.get import hep.dataforge.meta.number import kotlin.math.PI -object World { - val ZERO = Point3D(0.0, 0.0, 0.0) - val ONE = Point3D(1.0, 1.0, 1.0) +public object World { + public val ZERO: Point3D = Point3D(0.0, 0.0, 0.0) + public val ONE: Point3D = Point3D(1.0, 1.0, 1.0) } -const val PI2: Float = 2 * PI.toFloat() +public const val PI2: Float = 2 * PI.toFloat() -expect class Point2D(x: Number, y: Number) { - var x: Double - var y: Double +public expect class Point2D(x: Number, y: Number) { + public var x: Double + public var y: Double } -operator fun Point2D.component1() = x -operator fun Point2D.component2() = y +public operator fun Point2D.component1(): Double = x +public operator fun Point2D.component2(): Double = y -fun Point2D.toMeta() = Meta { +public fun Point2D.toMeta(): Meta = Meta { Solid.X_KEY put x Solid.Y_KEY put y } -fun Meta.point2D() = Point2D(this["x"].number ?: 0, this["y"].number ?: 0) +internal fun Meta.point2D(): Point2D = Point2D(this["x"].number ?: 0, this["y"].number ?: 0) -expect class Point3D(x: Number, y: Number, z: Number) { - var x: Double - var y: Double - var z: Double +public expect class Point3D(x: Number, y: Number, z: Number) { + public var x: Double + public var y: Double + public var z: Double } -expect operator fun Point3D.plus(other: Point3D): Point3D +public expect operator fun Point3D.plus(other: Point3D): Point3D -operator fun Point3D.component1() = x -operator fun Point3D.component2() = y -operator fun Point3D.component3() = z +public operator fun Point3D.component1(): Double = x +public operator fun Point3D.component2(): Double = y +public operator fun Point3D.component3(): Double = z -fun Meta.point3D() = Point3D(this["x"].number ?: 0, this["y"].number ?: 0, this["y"].number ?: 0) +internal fun Meta.point3D() = Point3D(this["x"].number ?: 0, this["y"].number ?: 0, this["y"].number ?: 0) -fun Point3D.toMeta() = Meta { +public fun Point3D.toMeta(): MetaBuilder = Meta { Solid.X_KEY put x Solid.Y_KEY put y Solid.Z_KEY put z diff --git a/visionforge-solid/src/commonMain/kotlin/hep/dataforge/vision/solid/serialization.kt b/visionforge-solid/src/commonMain/kotlin/hep/dataforge/vision/solid/serialization.kt index 0b0a4d0b..25724fab 100644 --- a/visionforge-solid/src/commonMain/kotlin/hep/dataforge/vision/solid/serialization.kt +++ b/visionforge-solid/src/commonMain/kotlin/hep/dataforge/vision/solid/serialization.kt @@ -2,6 +2,7 @@ package hep.dataforge.vision.solid import hep.dataforge.meta.DFExperimental import hep.dataforge.meta.double +import hep.dataforge.meta.transformations.MetaConverter.Companion.double import hep.dataforge.names.NameToken import hep.dataforge.vision.MutableVisionGroup import hep.dataforge.vision.Vision @@ -10,34 +11,19 @@ import kotlinx.serialization.* import kotlinx.serialization.builtins.MapSerializer import kotlinx.serialization.builtins.nullable import kotlinx.serialization.builtins.serializer +import kotlinx.serialization.descriptors.SerialDescriptor +import kotlinx.serialization.descriptors.buildClassSerialDescriptor +import kotlinx.serialization.descriptors.element +import kotlinx.serialization.encoding.* -inline fun Decoder.decodeStructure( - desc: SerialDescriptor, - vararg typeParams: KSerializer<*> = emptyArray(), - crossinline block: CompositeDecoder.() -> R -): R { - val decoder = beginStructure(desc, *typeParams) - val res = decoder.block() - decoder.endStructure(desc) - return res -} - -inline fun Encoder.encodeStructure( - desc: SerialDescriptor, - vararg typeParams: KSerializer<*> = emptyArray(), - block: CompositeEncoder.() -> Unit -) { - val encoder = beginStructure(desc, *typeParams) - encoder.block() - encoder.endStructure(desc) -} +@OptIn(ExperimentalSerializationApi::class) @Serializer(Point3D::class) -object Point3DSerializer : KSerializer { - override val descriptor: SerialDescriptor = SerialDescriptor("hep.dataforge.vis.spatial.Point3D") { - double("x", true) - double("y", true) - double("z", true) +public object Point3DSerializer : KSerializer { + override val descriptor: SerialDescriptor = buildClassSerialDescriptor("hep.dataforge.vis.spatial.Point3D") { + element("x") + element("y") + element("z") } override fun deserialize(decoder: Decoder): Point3D { @@ -47,7 +33,7 @@ object Point3DSerializer : KSerializer { decoder.decodeStructure(descriptor) { loop@ while (true) { when (val i = decodeElementIndex(descriptor)) { - CompositeDecoder.READ_DONE -> break@loop + CompositeDecoder.DECODE_DONE -> break@loop 0 -> x = decodeNullableSerializableElement(descriptor, 0, Double.serializer().nullable) ?: 0.0 1 -> y = decodeNullableSerializableElement(descriptor, 1, Double.serializer().nullable) ?: 0.0 2 -> z = decodeNullableSerializableElement(descriptor, 2, Double.serializer().nullable) ?: 0.0 @@ -67,11 +53,12 @@ object Point3DSerializer : KSerializer { } } +@OptIn(ExperimentalSerializationApi::class) @Serializer(Point2D::class) -object Point2DSerializer : KSerializer { - override val descriptor: SerialDescriptor = SerialDescriptor("hep.dataforge.vis.spatial.Point2D") { - double("x", true) - double("y", true) +public object Point2DSerializer : KSerializer { + override val descriptor: SerialDescriptor = buildClassSerialDescriptor("hep.dataforge.vis.spatial.Point2D") { + element("x") + element("y") } override fun deserialize(decoder: Decoder): Point2D { @@ -80,7 +67,7 @@ object Point2DSerializer : KSerializer { decoder.decodeStructure(descriptor) { loop@ while (true) { when (val i = decodeElementIndex(descriptor)) { - CompositeDecoder.READ_DONE -> break@loop + CompositeDecoder.DECODE_DONE -> break@loop 0 -> x = decodeNullableSerializableElement(descriptor, 0, Double.serializer().nullable) ?: 0.0 1 -> y = decodeNullableSerializableElement(descriptor, 1, Double.serializer().nullable) ?: 0.0 else -> throw SerializationException("Unknown index $i") @@ -98,6 +85,7 @@ object Point2DSerializer : KSerializer { } } +@OptIn(ExperimentalSerializationApi::class) @Serializer(MutableVisionGroup::class) internal object PrototypesSerializer : KSerializer { @@ -120,10 +108,10 @@ internal object PrototypesSerializer : KSerializer { } @OptIn(DFExperimental::class) -fun Vision.stringify(): String = SolidManager.jsonForSolids.stringify(Vision.serializer(), this) +public fun Vision.encodeToString(): String = SolidManager.jsonForSolids.encodeToString(Vision.serializer(), this) @OptIn(DFExperimental::class) -fun Vision.Companion.parseJson(str: String) = SolidManager.jsonForSolids.parse(serializer(), str).also { +public fun Vision.Companion.decodeFromString(str: String): Vision = SolidManager.jsonForSolids.decodeFromString(serializer(), str).also { if(it is VisionGroup){ it.attachChildren() } diff --git a/visionforge-solid/src/commonMain/kotlin/hep/dataforge/vision/solid/specifications/Axes.kt b/visionforge-solid/src/commonMain/kotlin/hep/dataforge/vision/solid/specifications/Axes.kt index 8a45e0a4..5e835c83 100644 --- a/visionforge-solid/src/commonMain/kotlin/hep/dataforge/vision/solid/specifications/Axes.kt +++ b/visionforge-solid/src/commonMain/kotlin/hep/dataforge/vision/solid/specifications/Axes.kt @@ -2,13 +2,13 @@ package hep.dataforge.vision.solid.specifications import hep.dataforge.meta.* -class Axes : Scheme() { - var visible by boolean(!config.isEmpty()) - var size by double(AXIS_SIZE) - var width by double(AXIS_WIDTH) +public class Axes : Scheme() { + public var visible: Boolean by boolean(!config.isEmpty()) + public var size: Double by double(AXIS_SIZE) + public var width: Double by double(AXIS_WIDTH) - companion object : SchemeSpec(::Axes) { - const val AXIS_SIZE = 1000.0 - const val AXIS_WIDTH = 3.0 + public companion object : SchemeSpec(::Axes) { + public const val AXIS_SIZE: Double = 1000.0 + public const val AXIS_WIDTH: Double = 3.0 } } \ No newline at end of file diff --git a/visionforge-solid/src/commonMain/kotlin/hep/dataforge/vision/solid/specifications/Camera.kt b/visionforge-solid/src/commonMain/kotlin/hep/dataforge/vision/solid/specifications/Camera.kt index dbd79bd8..396df8a4 100644 --- a/visionforge-solid/src/commonMain/kotlin/hep/dataforge/vision/solid/specifications/Camera.kt +++ b/visionforge-solid/src/commonMain/kotlin/hep/dataforge/vision/solid/specifications/Camera.kt @@ -6,24 +6,24 @@ import hep.dataforge.meta.double import hep.dataforge.meta.int import kotlin.math.PI -class Camera : Scheme() { - var fov by int(FIELD_OF_VIEW) +public class Camera : Scheme() { + public var fov: Int by int(FIELD_OF_VIEW) //var aspect by double(1.0) - var nearClip by double(NEAR_CLIP) - var farClip by double(FAR_CLIP) + public var nearClip: Double by double(NEAR_CLIP) + public var farClip: Double by double(FAR_CLIP) - var distance by double(INITIAL_DISTANCE) - var azimuth by double(INITIAL_AZIMUTH) - var latitude by double(INITIAL_LATITUDE) - val zenith: Double get() = PI / 2 - latitude + public var distance: Double by double(INITIAL_DISTANCE) + public var azimuth: Double by double(INITIAL_AZIMUTH) + public var latitude: Double by double(INITIAL_LATITUDE) + public val zenith: Double get() = PI / 2 - latitude - companion object : SchemeSpec(::Camera) { - const val INITIAL_DISTANCE = 300.0 - const val INITIAL_AZIMUTH = 0.0 - const val INITIAL_LATITUDE = PI / 6 - const val NEAR_CLIP = 0.1 - const val FAR_CLIP = 10000.0 - const val FIELD_OF_VIEW = 75 + public companion object : SchemeSpec(::Camera) { + public const val INITIAL_DISTANCE: Double = 300.0 + public const val INITIAL_AZIMUTH: Double = 0.0 + public const val INITIAL_LATITUDE: Double = PI / 6 + public const val NEAR_CLIP: Double = 0.1 + public const val FAR_CLIP: Double = 10000.0 + public const val FIELD_OF_VIEW: Int = 75 } } \ No newline at end of file diff --git a/visionforge-solid/src/commonMain/kotlin/hep/dataforge/vision/solid/specifications/Canvas3DOptions.kt b/visionforge-solid/src/commonMain/kotlin/hep/dataforge/vision/solid/specifications/Canvas3DOptions.kt index 9e4ceed6..33ba4bd0 100644 --- a/visionforge-solid/src/commonMain/kotlin/hep/dataforge/vision/solid/specifications/Canvas3DOptions.kt +++ b/visionforge-solid/src/commonMain/kotlin/hep/dataforge/vision/solid/specifications/Canvas3DOptions.kt @@ -5,11 +5,11 @@ import hep.dataforge.meta.SchemeSpec import hep.dataforge.meta.int import hep.dataforge.meta.spec -class Canvas3DOptions : Scheme() { - var axes by spec(Axes, Axes.empty()) - var camera by spec(Camera, Camera.empty()) - var controls by spec(Controls, Controls.empty()) - var minSize by int(300) +public class Canvas3DOptions : Scheme() { + public var axes: Axes by spec(Axes, Axes.empty()) + public var camera: Camera by spec(Camera, Camera.empty()) + public var controls: Controls by spec(Controls, Controls.empty()) + public var minSize: Int by int(300) - companion object : SchemeSpec(::Canvas3DOptions) + public companion object : SchemeSpec(::Canvas3DOptions) } \ No newline at end of file diff --git a/visionforge-solid/src/commonMain/kotlin/hep/dataforge/vision/solid/transform/RemoveSingleChild.kt b/visionforge-solid/src/commonMain/kotlin/hep/dataforge/vision/solid/transform/RemoveSingleChild.kt index 36b6db76..2fc1ffdb 100644 --- a/visionforge-solid/src/commonMain/kotlin/hep/dataforge/vision/solid/transform/RemoveSingleChild.kt +++ b/visionforge-solid/src/commonMain/kotlin/hep/dataforge/vision/solid/transform/RemoveSingleChild.kt @@ -1,5 +1,6 @@ package hep.dataforge.vision.solid.transform +import hep.dataforge.meta.DFExperimental import hep.dataforge.meta.update import hep.dataforge.names.asName import hep.dataforge.vision.MutableVisionGroup @@ -7,6 +8,7 @@ import hep.dataforge.vision.Vision import hep.dataforge.vision.VisionGroup import hep.dataforge.vision.solid.* +@DFExperimental internal fun mergeChild(parent: VisionGroup, child: Vision): Vision { return child.apply { @@ -32,6 +34,7 @@ internal fun mergeChild(parent: VisionGroup, child: Vision): Vision { } } +@DFExperimental object RemoveSingleChild : VisualTreeTransform() { override fun SolidGroup.transformInPlace() { diff --git a/visionforge-solid/src/commonMain/kotlin/hep/dataforge/vision/solid/transform/UnRef.kt b/visionforge-solid/src/commonMain/kotlin/hep/dataforge/vision/solid/transform/UnRef.kt index 1eeec5ad..9028b667 100644 --- a/visionforge-solid/src/commonMain/kotlin/hep/dataforge/vision/solid/transform/UnRef.kt +++ b/visionforge-solid/src/commonMain/kotlin/hep/dataforge/vision/solid/transform/UnRef.kt @@ -1,5 +1,6 @@ package hep.dataforge.vision.solid.transform +import hep.dataforge.meta.DFExperimental import hep.dataforge.names.Name import hep.dataforge.names.asName import hep.dataforge.vision.MutableVisionGroup @@ -7,6 +8,7 @@ import hep.dataforge.vision.VisionGroup import hep.dataforge.vision.solid.Proxy import hep.dataforge.vision.solid.SolidGroup +@DFExperimental object UnRef : VisualTreeTransform() { private fun VisionGroup.countRefs(): Map { return children.values.fold(HashMap()) { reducer, obj -> diff --git a/visionforge-solid/src/commonTest/kotlin/hep/dataforge/vision/solid/ConvexTest.kt b/visionforge-solid/src/commonTest/kotlin/hep/dataforge/vision/solid/ConvexTest.kt index 0afb5a7c..7da077bd 100644 --- a/visionforge-solid/src/commonTest/kotlin/hep/dataforge/vision/solid/ConvexTest.kt +++ b/visionforge-solid/src/commonTest/kotlin/hep/dataforge/vision/solid/ConvexTest.kt @@ -1,6 +1,7 @@ package hep.dataforge.vision.solid import hep.dataforge.meta.* +import kotlinx.serialization.json.toJson import kotlin.test.Test import kotlin.test.assertEquals @@ -24,7 +25,7 @@ class ConvexTest { val convex = group.children.values.first() as Convex - val json = SolidManager.jsonForSolids.toJson(Convex.serializer(), convex) + val json = SolidManager.jsonForSolids.encodeToJsonElement(Convex.serializer(), convex) val meta = json.toMetaItem().node!! val points = meta.getIndexed("points").values.map { (it as MetaItem.NodeItem<*>).node.point3D() } diff --git a/visionforge-solid/src/commonTest/kotlin/hep/dataforge/vision/solid/SerializationTest.kt b/visionforge-solid/src/commonTest/kotlin/hep/dataforge/vision/solid/SerializationTest.kt index f52b5c25..57b94441 100644 --- a/visionforge-solid/src/commonTest/kotlin/hep/dataforge/vision/solid/SerializationTest.kt +++ b/visionforge-solid/src/commonTest/kotlin/hep/dataforge/vision/solid/SerializationTest.kt @@ -1,11 +1,26 @@ package hep.dataforge.vision.solid +import hep.dataforge.names.Name import hep.dataforge.names.toName +import hep.dataforge.vision.MutableVisionGroup import hep.dataforge.vision.Vision import hep.dataforge.vision.get import kotlin.test.Test import kotlin.test.assertEquals +/** + * Create and attach new proxied group + */ +fun SolidGroup.proxyGroup( + name: String, + templateName: Name = name.toName(), + block: MutableVisionGroup.() -> Unit +): Proxy { + val group = SolidGroup().apply(block) + return proxy(name, group, templateName) +} + + class SerializationTest { @Test fun testCubeSerialization() { @@ -14,9 +29,9 @@ class SerializationTest { x = 100 z = -100 } - val string = cube.stringify() + val string = cube.encodeToString() println(string) - val newCube = Vision.parseJson(string) + val newCube = Vision.decodeFromString(string) assertEquals(cube.config, newCube.config) } @@ -35,9 +50,9 @@ class SerializationTest { } } } - val string = group.stringify() + val string = group.encodeToString() println(string) - val reconstructed = SolidGroup.parseJson(string) + val reconstructed = SolidGroup.decodeFromString(string) assertEquals(group["cube"]?.config, reconstructed["cube"]?.config) } diff --git a/visionforge-solid/src/jsMain/kotlin/hep/dataforge/vision/solid/geometryJs.kt b/visionforge-solid/src/jsMain/kotlin/hep/dataforge/vision/solid/geometryJs.kt index 8aa5fe91..170e8249 100644 --- a/visionforge-solid/src/jsMain/kotlin/hep/dataforge/vision/solid/geometryJs.kt +++ b/visionforge-solid/src/jsMain/kotlin/hep/dataforge/vision/solid/geometryJs.kt @@ -5,10 +5,10 @@ import info.laht.threekt.math.Vector2 import info.laht.threekt.math.Vector3 import info.laht.threekt.math.plus -actual typealias Point2D = Vector2 +public actual typealias Point2D = Vector2 -actual typealias Point3D = Vector3 +public actual typealias Point3D = Vector3 -actual operator fun Point3D.plus(other: Point3D): Point3D { +public actual operator fun Point3D.plus(other: Point3D): Point3D { return this.plus(other) } \ No newline at end of file diff --git a/visionforge-solid/src/jsMain/kotlin/hep/dataforge/vision/solid/three/ThreeFactory.kt b/visionforge-solid/src/jsMain/kotlin/hep/dataforge/vision/solid/three/ThreeFactory.kt index c432fbd3..28bb21d6 100644 --- a/visionforge-solid/src/jsMain/kotlin/hep/dataforge/vision/solid/three/ThreeFactory.kt +++ b/visionforge-solid/src/jsMain/kotlin/hep/dataforge/vision/solid/three/ThreeFactory.kt @@ -8,6 +8,7 @@ import hep.dataforge.vision.solid.* import hep.dataforge.vision.solid.SolidMaterial.Companion.MATERIAL_KEY import hep.dataforge.vision.solid.three.ThreeFactory.Companion.TYPE import hep.dataforge.vision.solid.three.ThreeMaterials.getMaterial +import hep.dataforge.vision.visible import info.laht.threekt.core.BufferGeometry import info.laht.threekt.core.Object3D import info.laht.threekt.objects.Mesh @@ -54,7 +55,7 @@ fun Object3D.updateProperty(source: Vision, propertyName: Name) { ) { //update position of mesh using this object updatePosition(source) - } else if (propertyName == Solid.VISIBLE_KEY) { + } else if (propertyName == Vision.VISIBLE_KEY) { visible = source.visible ?: true } } diff --git a/visionforge-solid/src/jsMain/kotlin/hep/dataforge/vision/solid/three/ThreePlugin.kt b/visionforge-solid/src/jsMain/kotlin/hep/dataforge/vision/solid/three/ThreePlugin.kt index d8f467fe..546cb882 100644 --- a/visionforge-solid/src/jsMain/kotlin/hep/dataforge/vision/solid/three/ThreePlugin.kt +++ b/visionforge-solid/src/jsMain/kotlin/hep/dataforge/vision/solid/three/ThreePlugin.kt @@ -5,6 +5,7 @@ import hep.dataforge.meta.Meta import hep.dataforge.names.* import hep.dataforge.vision.Vision import hep.dataforge.vision.solid.* +import hep.dataforge.vision.visible import info.laht.threekt.core.Object3D import kotlin.collections.set import kotlin.reflect.KClass @@ -30,7 +31,7 @@ class ThreePlugin : AbstractPlugin() { @Suppress("UNCHECKED_CAST") private fun findObjectFactory(type: KClass): ThreeFactory? { return (objectFactories[type] - ?: context.content>(ThreeFactory.TYPE).values.find { it.type == type }) + ?: context.gather>(ThreeFactory.TYPE).values.find { it.type == type }) as ThreeFactory? } @@ -63,7 +64,7 @@ class ThreePlugin : AbstractPlugin() { ) { //update position of mesh using this object updatePosition(obj) - } else if (name == Solid.VISIBLE_KEY) { + } else if (name == Vision.VISIBLE_KEY) { visible = obj.visible ?: true } } @@ -123,28 +124,28 @@ internal fun Object3D.getOrCreateGroup(name: Name): Object3D { return when { name.isEmpty() -> this name.length == 1 -> { - val token = name.first()!! + val token = name.tokens.first() children.find { it.name == token.toString() } ?: info.laht.threekt.objects.Group().also { group -> group.name = token.toString() this.add(group) } } - else -> getOrCreateGroup(name.first()!!.asName()).getOrCreateGroup(name.cutFirst()) + else -> getOrCreateGroup(name.tokens.first().asName()).getOrCreateGroup(name.cutFirst()) } } internal operator fun Object3D.set(name: Name, obj: Object3D) { when (name.length) { 0 -> error("Can't set object with an empty name") - 1 -> set(name.first()!!, obj) - else -> getOrCreateGroup(name.cutLast())[name.last()!!] = obj + 1 -> set(name.tokens.first(), obj) + else -> getOrCreateGroup(name.cutLast())[name.tokens.last()] = obj } } internal fun Object3D.findChild(name: Name): Object3D? { return when { name.isEmpty() -> this - name.length == 1 -> this.children.find { it.name == name.first()!!.toString() } - else -> findChild(name.first()!!.asName())?.findChild(name.cutFirst()) + name.length == 1 -> this.children.find { it.name == name.tokens.first().toString() } + else -> findChild(name.tokens.first().asName())?.findChild(name.cutFirst()) } } \ No newline at end of file diff --git a/visionforge-solid/src/jsMain/kotlin/hep/dataforge/vision/solid/three/ThreeProxyFactory.kt b/visionforge-solid/src/jsMain/kotlin/hep/dataforge/vision/solid/three/ThreeProxyFactory.kt index 832dd32d..b6321d25 100644 --- a/visionforge-solid/src/jsMain/kotlin/hep/dataforge/vision/solid/three/ThreeProxyFactory.kt +++ b/visionforge-solid/src/jsMain/kotlin/hep/dataforge/vision/solid/three/ThreeProxyFactory.kt @@ -1,5 +1,7 @@ package hep.dataforge.vision.solid.three +import hep.dataforge.names.cutFirst +import hep.dataforge.names.firstOrNull import hep.dataforge.names.toName import hep.dataforge.vision.solid.Proxy import hep.dataforge.vision.solid.Proxy.Companion.PROXY_CHILD_PROPERTY_PREFIX @@ -42,8 +44,8 @@ class ThreeProxyFactory(val three: ThreePlugin) : ThreeFactory { } obj.onPropertyChange(this) { name -> - if (name.first()?.body == PROXY_CHILD_PROPERTY_PREFIX) { - val childName = name.first()?.index?.toName() ?: error("Wrong syntax for proxy child property: '$name'") + if (name.firstOrNull()?.body == PROXY_CHILD_PROPERTY_PREFIX) { + val childName = name.firstOrNull()?.index?.toName() ?: error("Wrong syntax for proxy child property: '$name'") val propertyName = name.cutFirst() val proxyChild = obj[childName] ?: error("Proxy child with name '$childName' not found") val child = object3D.findChild(childName) ?: error("Object child with name '$childName' not found") diff --git a/visionforge-solid/src/jsMain/kotlin/hep/dataforge/vision/solid/three/outputConfig.kt b/visionforge-solid/src/jsMain/kotlin/hep/dataforge/vision/solid/three/outputConfig.kt index 2956f8cc..f4e65da1 100644 --- a/visionforge-solid/src/jsMain/kotlin/hep/dataforge/vision/solid/three/outputConfig.kt +++ b/visionforge-solid/src/jsMain/kotlin/hep/dataforge/vision/solid/three/outputConfig.kt @@ -38,7 +38,7 @@ fun RBuilder.canvasControls(canvas: ThreeCanvas) = accordion("controls") { div("row") { div("col-2") { label("checkbox-inline") { - input(type = InputType.checkBox){ + input(type = InputType.checkBox) { attrs { defaultChecked = canvas.axes.visible onChangeFunction = { @@ -55,7 +55,7 @@ fun RBuilder.canvasControls(canvas: ThreeCanvas) = accordion("controls") { attrs { onClickFunction = { val json = (canvas.content as? SolidGroup)?.let { group -> - SolidManager.jsonForSolids.stringify( + SolidManager.jsonForSolids.encodeToString( SolidGroup.serializer(), group ) @@ -76,7 +76,7 @@ fun RBuilder.canvasControls(canvas: ThreeCanvas) = accordion("controls") { (0..11).forEach { layer -> div("col-1") { label { +layer.toString() } - input(type = InputType.checkBox){ + input(type = InputType.checkBox) { attrs { if (layer == 0) { defaultChecked = true @@ -119,7 +119,7 @@ fun Element.displayCanvasControls(canvas: ThreeCanvas, block: TagConsumer - SolidManager.jsonForSolids.stringify( + SolidManager.jsonForSolids.encodeToString( SolidGroup.serializer(), group ) diff --git a/visionforge-solid/src/jvmMain/kotlin/hep/dataforge/vision/solid/fx/FX3DPlugin.kt b/visionforge-solid/src/jvmMain/kotlin/hep/dataforge/vision/solid/fx/FX3DPlugin.kt index 0b2f064f..712b2b2e 100644 --- a/visionforge-solid/src/jvmMain/kotlin/hep/dataforge/vision/solid/fx/FX3DPlugin.kt +++ b/visionforge-solid/src/jvmMain/kotlin/hep/dataforge/vision/solid/fx/FX3DPlugin.kt @@ -38,7 +38,7 @@ class FX3DPlugin : AbstractPlugin() { @Suppress("UNCHECKED_CAST") private fun findObjectFactory(type: KClass): FX3DFactory? { - return (objectFactories[type] ?: context.content>(TYPE).values.find { it.type == type }) + return (objectFactories[type] ?: context.gather>(TYPE).values.find { it.type == type }) as FX3DFactory? } diff --git a/visionforge-solid/src/jvmMain/kotlin/hep/dataforge/vision/solid/fx/FXProxyFactory.kt b/visionforge-solid/src/jvmMain/kotlin/hep/dataforge/vision/solid/fx/FXProxyFactory.kt index 6a171854..3dca5113 100644 --- a/visionforge-solid/src/jvmMain/kotlin/hep/dataforge/vision/solid/fx/FXProxyFactory.kt +++ b/visionforge-solid/src/jvmMain/kotlin/hep/dataforge/vision/solid/fx/FXProxyFactory.kt @@ -1,8 +1,6 @@ package hep.dataforge.vision.solid.fx -import hep.dataforge.names.Name -import hep.dataforge.names.isEmpty -import hep.dataforge.names.toName +import hep.dataforge.names.* import hep.dataforge.vision.Vision import hep.dataforge.vision.solid.Proxy import javafx.scene.Group @@ -17,8 +15,8 @@ class FXProxyFactory(val plugin: FX3DPlugin) : FX3DFactory { val node = plugin.buildNode(prototype) obj.onPropertyChange(this) { name-> - if (name.first()?.body == Proxy.PROXY_CHILD_PROPERTY_PREFIX) { - val childName = name.first()?.index?.toName() ?: error("Wrong syntax for proxy child property: '$name'") + if (name.firstOrNull()?.body == Proxy.PROXY_CHILD_PROPERTY_PREFIX) { + val childName = name.firstOrNull()?.index?.toName() ?: error("Wrong syntax for proxy child property: '$name'") val propertyName = name.cutFirst() val proxyChild = obj[childName] ?: error("Proxy child with name '$childName' not found") val child = node.findChild(childName) ?: error("Object child with name '$childName' not found") @@ -35,7 +33,7 @@ private fun Node.findChild(name: Name): Node? { } else { (this as? Group) ?.children - ?.find { it.properties["name"] as String == name.first()?.toString() } + ?.find { it.properties["name"] as String == name.firstOrNull()?.toString() } ?.findChild(name.cutFirst()) } } diff --git a/visionforge-solid/src/jvmMain/kotlin/hep/dataforge/vision/solid/generateSchema.kt b/visionforge-solid/src/jvmMain/kotlin/hep/dataforge/vision/solid/generateSchema.kt index 122f051b..9d3c332b 100644 --- a/visionforge-solid/src/jvmMain/kotlin/hep/dataforge/vision/solid/generateSchema.kt +++ b/visionforge-solid/src/jvmMain/kotlin/hep/dataforge/vision/solid/generateSchema.kt @@ -1,205 +1,208 @@ -package hep.dataforge.vision.solid - -import hep.dataforge.meta.JSON_PRETTY -import kotlinx.serialization.* -import kotlinx.serialization.json.* -import kotlinx.serialization.modules.SerialModule -import kotlinx.serialization.modules.SerialModuleCollector -import kotlin.reflect.KClass - -private fun SerialDescriptor.getJsonType() = when (this.kind) { - StructureKind.LIST -> "array" - PrimitiveKind.BYTE, PrimitiveKind.SHORT, PrimitiveKind.INT, PrimitiveKind.LONG, - PrimitiveKind.FLOAT, PrimitiveKind.DOUBLE -> "number" - PrimitiveKind.STRING, PrimitiveKind.CHAR, UnionKind.ENUM_KIND -> "string" - PrimitiveKind.BOOLEAN -> "boolean" - else -> "object" -} - -private fun SerialDescriptor.isVisualObject() = serialName.startsWith("solid")||serialName.startsWith("group.solid") - -private const val definitionNode = "\$defs" - -private fun SerialModule.enumerate(type: KClass<*>): Sequence { - val list = ArrayList() - fun send(descriptor: SerialDescriptor) = list.add(descriptor) - - val enumerator = object : SerialModuleCollector { - override fun contextual(kClass: KClass, serializer: KSerializer) { - if (kClass == type) { - send(serializer.descriptor) - } - } - - override fun polymorphic( - baseClass: KClass, - actualClass: KClass, - actualSerializer: KSerializer - ) { - if (baseClass == type) { - send(actualSerializer.descriptor) - } - } - - } - dumpTo(enumerator) - return list.asSequence() -} - -/** - * Creates an [JsonObject] which contains Json Schema of given [descriptor]. - * - * Schema can contain following fields: - * `description`, `type` for all descriptors; - * `properties` and `required` for objects; - * `enum` for enums; - * `items` for arrays. - * - * User can modify this schema to add additional validation keywords - * (as per [https://json-schema.org/latest/json-schema-validation.html]) - * if they want. - */ -private fun jsonSchema(descriptor: SerialDescriptor, context: SerialModule): JsonObject { - - if (descriptor.serialName in arrayOf( - "hep.dataforge.vision.solid.Point3D", - "hep.dataforge.vision.solid.Point3D?", - "hep.dataforge.vision.solid.Point2D", - "hep.dataforge.vision.solid.Point2D?", - "hep.dataforge.meta.Meta", - "hep.dataforge.meta.Meta?" - ) - ) return json { - "\$ref" to "#/$definitionNode/${descriptor.serialName.replace("?", "")}" - } - - - val properties: MutableMap = mutableMapOf() - val requiredProperties: MutableSet = mutableSetOf() - val isEnum = descriptor.kind == UnionKind.ENUM_KIND - val isPolymorphic = descriptor.kind is PolymorphicKind - - - if (!isEnum && !isPolymorphic) descriptor.elementDescriptors().forEachIndexed { index, child -> - val elementName = descriptor.getElementName(index) - - val elementSchema = when (elementName) { - "properties" -> json { - "\$ref" to "#/$definitionNode/hep.dataforge.meta.Meta" - } - "first", "second" -> json { - "\$ref" to "#/$definitionNode/children" - } - "styleSheet" -> json { - "type" to "object" - "additionalProperties" to json { - "\$ref" to "#/$definitionNode/hep.dataforge.meta.Meta" - } - } - in arrayOf("children", "prototypes") -> json { - "type" to "object" - "additionalProperties" to json { - "\$ref" to "#/$definitionNode/children" - } - } - else -> jsonSchema(child, context) - } - properties[elementName] = elementSchema - - if (!descriptor.isElementOptional(index)) requiredProperties.add(elementName) - } - - val jsonType = descriptor.getJsonType() - val objectData: MutableMap = mutableMapOf( - "description" to JsonLiteral(descriptor.serialName), - "type" to JsonLiteral(jsonType) - ) - if (isEnum) { - val allElementNames = (0 until descriptor.elementsCount).map(descriptor::getElementName) - objectData += "enum" to JsonArray(allElementNames.map(::JsonLiteral)) - } - when (jsonType) { - "object" -> { - if(descriptor.isVisualObject()) { - properties["type"] = json { - "const" to descriptor.serialName - } - } - objectData["properties"] = JsonObject(properties) - val required = requiredProperties.map { JsonLiteral(it) } - if (required.isNotEmpty()) { - objectData["required"] = JsonArray(required) - } - } - "array" -> objectData["items"] = properties.values.let { - check(it.size == 1) { "Array descriptor has returned inconsistent number of elements: expected 1, found ${it.size}" } - it.first() - } - else -> { /* no-op */ - } - } - return JsonObject(objectData) -} - -fun main() { - val context = SolidManager.serialModule - val definitions = json { - "children" to json { - "anyOf" to jsonArray { - context.enumerate(Solid::class).forEach { - if (it.serialName == "hep.dataforge.vis.spatial.SolidGroup") { - +json { - "\$ref" to "#/$definitionNode/${it.serialName}" - } - } else { - +jsonSchema(it, context) - } - } - } - } - "hep.dataforge.meta.Meta" to json { - "type" to "object" - } - "hep.dataforge.vision.solid.Point3D" to json { - "type" to "object" - "properties" to json { - "x" to json { - "type" to "number" - } - "y" to json { - "type" to "number" - } - "z" to json { - "type" to "number" - } - } - } - "hep.dataforge.vision.solid.Point2D" to json { - "type" to "object" - "properties" to json { - "x" to json { - "type" to "number" - } - "y" to json { - "type" to "number" - } - } - } - "hep.dataforge.vision.solid.SolidGroup" to jsonSchema( - SolidGroup.serializer().descriptor, - context - ) - - } - - println( - JSON_PRETTY.stringify( - JsonObjectSerializer, - json { - "\$defs" to definitions - "\$ref" to "#/$definitionNode/hep.dataforge.vision.solid.SolidGroup" - } - ) - ) -} - +//package hep.dataforge.vision.solid +// +//import hep.dataforge.meta.JSON_PRETTY +//import kotlinx.serialization.* +//import kotlinx.serialization.descriptors.PrimitiveKind +//import kotlinx.serialization.descriptors.SerialDescriptor +//import kotlinx.serialization.descriptors.StructureKind +//import kotlinx.serialization.descriptors.UnionKind +//import kotlinx.serialization.json.* +//import kotlinx.serialization.modules.SerialModule +//import kotlin.reflect.KClass +// +//private fun SerialDescriptor.getJsonType() = when (this.kind) { +// StructureKind.LIST -> "array" +// PrimitiveKind.BYTE, PrimitiveKind.SHORT, PrimitiveKind.INT, PrimitiveKind.LONG, +// PrimitiveKind.FLOAT, PrimitiveKind.DOUBLE -> "number" +// PrimitiveKind.STRING, PrimitiveKind.CHAR, UnionKind.ENUM_KIND -> "string" +// PrimitiveKind.BOOLEAN -> "boolean" +// else -> "object" +//} +// +//private fun SerialDescriptor.isVisualObject() = serialName.startsWith("solid")||serialName.startsWith("group.solid") +// +//private const val definitionNode = "\$defs" +// +//private fun SerialModule.enumerate(type: KClass<*>): Sequence { +// val list = ArrayList() +// fun send(descriptor: SerialDescriptor) = list.add(descriptor) +// +// val enumerator = object : SerialModuleCollector { +// override fun contextual(kClass: KClass, serializer: KSerializer) { +// if (kClass == type) { +// send(serializer.descriptor) +// } +// } +// +// override fun polymorphic( +// baseClass: KClass, +// actualClass: KClass, +// actualSerializer: KSerializer +// ) { +// if (baseClass == type) { +// send(actualSerializer.descriptor) +// } +// } +// +// } +// dumpTo(enumerator) +// return list.asSequence() +//} +// +///** +// * Creates an [JsonObject] which contains Json Schema of given [descriptor]. +// * +// * Schema can contain following fields: +// * `description`, `type` for all descriptors; +// * `properties` and `required` for objects; +// * `enum` for enums; +// * `items` for arrays. +// * +// * User can modify this schema to add additional validation keywords +// * (as per [https://json-schema.org/latest/json-schema-validation.html]) +// * if they want. +// */ +//private fun jsonSchema(descriptor: SerialDescriptor, context: SerialModule): JsonObject { +// +// if (descriptor.serialName in arrayOf( +// "hep.dataforge.vision.solid.Point3D", +// "hep.dataforge.vision.solid.Point3D?", +// "hep.dataforge.vision.solid.Point2D", +// "hep.dataforge.vision.solid.Point2D?", +// "hep.dataforge.meta.Meta", +// "hep.dataforge.meta.Meta?" +// ) +// ) return json { +// "\$ref" to "#/$definitionNode/${descriptor.serialName.replace("?", "")}" +// } +// +// +// val properties: MutableMap = mutableMapOf() +// val requiredProperties: MutableSet = mutableSetOf() +// val isEnum = descriptor.kind == UnionKind.ENUM_KIND +// val isPolymorphic = descriptor.kind is PolymorphicKind +// +// +// if (!isEnum && !isPolymorphic) descriptor.elementDescriptors().forEachIndexed { index, child -> +// val elementName = descriptor.getElementName(index) +// +// val elementSchema = when (elementName) { +// "properties" -> buildJsonObject { +// put("\$ref", "#/$definitionNode/hep.dataforge.meta.Meta") +// } +// "first", "second" -> buildJsonObject { +// put("\$ref", "#/$definitionNode/children") +// } +// "styleSheet" -> buildJsonObject { +// put("type", "object") +// put("additionalProperties", buildJsonObject { +// put("\$ref", "#/$definitionNode/hep.dataforge.meta.Meta") +// }) +// } +// in arrayOf("children", "prototypes") -> buildJsonObject { +// put("type", "object") +// put("additionalProperties", buildJsonObject { +// put("\$ref", "#/$definitionNode/children") +// }) +// } +// else -> jsonSchema(child, context) +// } +// properties[elementName] = elementSchema +// +// if (!descriptor.isElementOptional(index)) requiredProperties.add(elementName) +// } +// +// val jsonType = descriptor.getJsonType() +// val objectData: MutableMap = mutableMapOf( +// "description" to JsonLiteral(descriptor.serialName), +// "type" to JsonLiteral(jsonType) +// ) +// if (isEnum) { +// val allElementNames = (0 until descriptor.elementsCount).map(descriptor::getElementName) +// objectData += "enum" to JsonArray(allElementNames.map(::JsonLiteral)) +// } +// when (jsonType) { +// "object" -> { +// if(descriptor.isVisualObject()) { +// properties["type"] = json { +// "const" to descriptor.serialName +// } +// } +// objectData["properties"] = JsonObject(properties) +// val required = requiredProperties.map { JsonLiteral(it) } +// if (required.isNotEmpty()) { +// objectData["required"] = JsonArray(required) +// } +// } +// "array" -> objectData["items"] = properties.values.let { +// check(it.size == 1) { "Array descriptor has returned inconsistent number of elements: expected 1, found ${it.size}" } +// it.first() +// } +// else -> { /* no-op */ +// } +// } +// return JsonObject(objectData) +//} +// +//fun main() { +// val context = SolidManager.serialModule +// val definitions = json { +// "children" to json { +// "anyOf" to jsonArray { +// context.enumerate(Solid::class).forEach { +// if (it.serialName == "hep.dataforge.vis.spatial.SolidGroup") { +// +json { +// "\$ref" to "#/$definitionNode/${it.serialName}" +// } +// } else { +// +jsonSchema(it, context) +// } +// } +// } +// } +// "hep.dataforge.meta.Meta" to json { +// "type" to "object" +// } +// "hep.dataforge.vision.solid.Point3D" to json { +// "type" to "object" +// "properties" to json { +// "x" to json { +// "type" to "number" +// } +// "y" to json { +// "type" to "number" +// } +// "z" to json { +// "type" to "number" +// } +// } +// } +// "hep.dataforge.vision.solid.Point2D" to json { +// "type" to "object" +// "properties" to json { +// "x" to json { +// "type" to "number" +// } +// "y" to json { +// "type" to "number" +// } +// } +// } +// "hep.dataforge.vision.solid.SolidGroup" to jsonSchema( +// SolidGroup.serializer().descriptor, +// context +// ) +// +// } +// +// println( +// JSON_PRETTY.stringify( +// JsonObjectSerializer, +// json { +// "\$defs" to definitions +// "\$ref" to "#/$definitionNode/hep.dataforge.vision.solid.SolidGroup" +// } +// ) +// ) +//} +// diff --git a/visionforge-solid/src/jvmMain/kotlin/hep/dataforge/vision/solid/geometryJVM.kt b/visionforge-solid/src/jvmMain/kotlin/hep/dataforge/vision/solid/geometryJVM.kt index 96f40d81..153aace7 100644 --- a/visionforge-solid/src/jvmMain/kotlin/hep/dataforge/vision/solid/geometryJVM.kt +++ b/visionforge-solid/src/jvmMain/kotlin/hep/dataforge/vision/solid/geometryJVM.kt @@ -1,11 +1,11 @@ package hep.dataforge.vision.solid import org.fxyz3d.geometry.Point3D as FXPoint3D -actual data class Point2D(actual var x: Double, actual var y: Double) { +public actual data class Point2D(public actual var x: Double, public actual var y: Double) { actual constructor(x: Number, y: Number) : this(x.toDouble(), y.toDouble()) } -actual class Point3D(val point: FXPoint3D) { +public actual class Point3D(val point: FXPoint3D) { actual constructor(x: Number, y: Number, z: Number) : this( FXPoint3D( x.toFloat(), @@ -14,19 +14,19 @@ actual class Point3D(val point: FXPoint3D) { ) ) - actual var x: Double + public actual var x: Double inline get() = point.x.toDouble() inline set(value) { point.x = value.toFloat() } - actual var y: Double + public actual var y: Double inline get() = point.y.toDouble() inline set(value) { point.y = value.toFloat() } - actual var z: Double + public actual var z: Double inline get() = point.z.toDouble() inline set(value) { point.z = value.toFloat() @@ -45,6 +45,6 @@ actual class Point3D(val point: FXPoint3D) { } } -actual operator fun Point3D.plus(other: Point3D): Point3D { +public actual operator fun Point3D.plus(other: Point3D): Point3D { return Point3D(point.add(other.point)) } \ No newline at end of file From c3001cd85897018cd2466ff3d0126de27998225a Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Tue, 6 Oct 2020 17:33:13 +0300 Subject: [PATCH 011/151] Fix for https://youtrack.jetbrains.com/issue/KT-42427 --- demo/gdml/build.gradle.kts | 5 ----- .../hep/dataforge/vision/gdml/demo/GDMLAppComponent.kt | 2 +- demo/muon-monitor/build.gradle.kts | 4 ---- .../jsMain/kotlin/ru/mipt/npm/muon/monitor/MMAppComponent.kt | 3 ++- .../main/kotlin/hep/dataforge/vision/react/ConfigEditor.kt | 4 ++-- .../src/main/kotlin/hep/dataforge/vision/react/MetaViewer.kt | 3 ++- .../src/main/kotlin/hep/dataforge/vision/react/ObjectTree.kt | 3 ++- .../main/kotlin/hep/dataforge/vision/react/valueChooser.kt | 5 +++-- .../hep/dataforge/vision/solid/three/ThreeCanvasComponent.kt | 5 +++-- 9 files changed, 15 insertions(+), 19 deletions(-) diff --git a/demo/gdml/build.gradle.kts b/demo/gdml/build.gradle.kts index b0a00e61..1824345c 100644 --- a/demo/gdml/build.gradle.kts +++ b/demo/gdml/build.gradle.kts @@ -20,11 +20,6 @@ kotlin { withJava() } } - - js { - useCommonJs() - } - sourceSets { commonMain { dependencies { diff --git a/demo/gdml/src/jsMain/kotlin/hep/dataforge/vision/gdml/demo/GDMLAppComponent.kt b/demo/gdml/src/jsMain/kotlin/hep/dataforge/vision/gdml/demo/GDMLAppComponent.kt index 2392e042..4b9a4e0d 100644 --- a/demo/gdml/src/jsMain/kotlin/hep/dataforge/vision/gdml/demo/GDMLAppComponent.kt +++ b/demo/gdml/src/jsMain/kotlin/hep/dataforge/vision/gdml/demo/GDMLAppComponent.kt @@ -31,7 +31,7 @@ import react.dom.h1 import styled.css import kotlin.math.PI -interface GDMLAppProps : RProps { +external interface GDMLAppProps : RProps { var context: Context var rootObject: Vision? var selected: Name? diff --git a/demo/muon-monitor/build.gradle.kts b/demo/muon-monitor/build.gradle.kts index f4ba471d..3e0cb8d9 100644 --- a/demo/muon-monitor/build.gradle.kts +++ b/demo/muon-monitor/build.gradle.kts @@ -31,10 +31,6 @@ kotlin { } } - js { - useCommonJs() - } - sourceSets { commonMain { dependencies { diff --git a/demo/muon-monitor/src/jsMain/kotlin/ru/mipt/npm/muon/monitor/MMAppComponent.kt b/demo/muon-monitor/src/jsMain/kotlin/ru/mipt/npm/muon/monitor/MMAppComponent.kt index 61deb655..a4540ebd 100644 --- a/demo/muon-monitor/src/jsMain/kotlin/ru/mipt/npm/muon/monitor/MMAppComponent.kt +++ b/demo/muon-monitor/src/jsMain/kotlin/ru/mipt/npm/muon/monitor/MMAppComponent.kt @@ -25,7 +25,7 @@ import react.RProps import react.dom.* import kotlin.math.PI -interface MMAppProps : RProps { +external interface MMAppProps : RProps { var model: Model var context: Context var connection: HttpClient @@ -40,6 +40,7 @@ private val canvasConfig = Canvas3DOptions { } } +@JsExport val MMApp = component { props -> var selected by state { props.selected } var canvas: ThreeCanvas? by state { null } diff --git a/ui/react/src/main/kotlin/hep/dataforge/vision/react/ConfigEditor.kt b/ui/react/src/main/kotlin/hep/dataforge/vision/react/ConfigEditor.kt index b7c4407e..6669f491 100644 --- a/ui/react/src/main/kotlin/hep/dataforge/vision/react/ConfigEditor.kt +++ b/ui/react/src/main/kotlin/hep/dataforge/vision/react/ConfigEditor.kt @@ -14,7 +14,7 @@ import react.* import react.dom.render import styled.* -interface ConfigEditorItemProps : RProps { +public external interface ConfigEditorItemProps : RProps { /** * Root config object - always non null @@ -190,7 +190,7 @@ private fun RFBuilder.configEditorItem(props: ConfigEditorItemProps) { } } -interface ConfigEditorProps : RProps { +public external interface ConfigEditorProps : RProps { var id: Name var root: Config var default: Meta? diff --git a/ui/react/src/main/kotlin/hep/dataforge/vision/react/MetaViewer.kt b/ui/react/src/main/kotlin/hep/dataforge/vision/react/MetaViewer.kt index 5f98e40f..48e49a19 100644 --- a/ui/react/src/main/kotlin/hep/dataforge/vision/react/MetaViewer.kt +++ b/ui/react/src/main/kotlin/hep/dataforge/vision/react/MetaViewer.kt @@ -17,7 +17,7 @@ import react.* import react.dom.a import styled.* -interface MetaViewerProps : RProps { +public external interface MetaViewerProps : RProps { /** * Root meta */ @@ -136,6 +136,7 @@ private fun RFBuilder.metaViewerItem(props: MetaViewerProps) { } } +@JsExport val MetaViewer = component { props -> child(MetaViewerItem) { attrs { diff --git a/ui/react/src/main/kotlin/hep/dataforge/vision/react/ObjectTree.kt b/ui/react/src/main/kotlin/hep/dataforge/vision/react/ObjectTree.kt index ece2a32b..91760b4a 100644 --- a/ui/react/src/main/kotlin/hep/dataforge/vision/react/ObjectTree.kt +++ b/ui/react/src/main/kotlin/hep/dataforge/vision/react/ObjectTree.kt @@ -12,7 +12,7 @@ import org.w3c.dom.events.Event import react.* import styled.* -interface ObjectTreeProps : RProps { +public external interface ObjectTreeProps : RProps { var name: Name var selected: Name? var obj: Vision @@ -102,6 +102,7 @@ private fun RFBuilder.objectTree(props: ObjectTreeProps): Unit { } } +@JsExport val ObjectTree: FunctionalComponent = component { props -> objectTree(props) } diff --git a/ui/react/src/main/kotlin/hep/dataforge/vision/react/valueChooser.kt b/ui/react/src/main/kotlin/hep/dataforge/vision/react/valueChooser.kt index cf51b5aa..e0888a46 100644 --- a/ui/react/src/main/kotlin/hep/dataforge/vision/react/valueChooser.kt +++ b/ui/react/src/main/kotlin/hep/dataforge/vision/react/valueChooser.kt @@ -19,16 +19,17 @@ import react.dom.option import styled.styledInput import styled.styledSelect -interface ValueChooserProps : RProps { +public external interface ValueChooserProps : RProps { var item: MetaItem<*>? var descriptor: ValueDescriptor? var valueChanged: ((Value?) -> Unit)? } -interface ValueChooserState : RState { +public external interface ValueChooserState : RState { var rawInput: Boolean? } +@JsExport class ValueChooserComponent(props: ValueChooserProps) : RComponent(props) { private val element = createRef() diff --git a/visionforge-solid/src/jsMain/kotlin/hep/dataforge/vision/solid/three/ThreeCanvasComponent.kt b/visionforge-solid/src/jsMain/kotlin/hep/dataforge/vision/solid/three/ThreeCanvasComponent.kt index eb9ed292..fbc90a62 100644 --- a/visionforge-solid/src/jsMain/kotlin/hep/dataforge/vision/solid/three/ThreeCanvasComponent.kt +++ b/visionforge-solid/src/jsMain/kotlin/hep/dataforge/vision/solid/three/ThreeCanvasComponent.kt @@ -13,7 +13,7 @@ import react.RState import react.dom.div import react.dom.findDOMNode -interface ThreeCanvasProps : RProps { +public external interface ThreeCanvasProps : RProps { var context: Context var obj: Solid var options: Canvas3DOptions? @@ -22,11 +22,12 @@ interface ThreeCanvasProps : RProps { var canvasCallback: ((ThreeCanvas?) -> Unit)? } -interface ThreeCanvasState : RState { +public external interface ThreeCanvasState : RState { var element: Element? // var canvas: ThreeCanvas? } +@JsExport class ThreeCanvasComponent : RComponent() { private var canvas: ThreeCanvas? = null From f72d626b0b880c32dd4b005fcc0f50eb5c110a4d Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Tue, 6 Oct 2020 17:50:36 +0300 Subject: [PATCH 012/151] Fix build for ring-ui --- ui/ring/build.gradle.kts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/ui/ring/build.gradle.kts b/ui/ring/build.gradle.kts index 167743be..a14662c4 100644 --- a/ui/ring/build.gradle.kts +++ b/ui/ring/build.gradle.kts @@ -4,6 +4,12 @@ plugins { val dataforgeVersion: String by rootProject.extra +kotlin{ + js{ + useCommonJs() + } +} + dependencies{ api(project(":ui:react")) From 072b036fa252a8bef01be92d0aac3f297a5b1c22 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Tue, 6 Oct 2020 18:45:58 +0300 Subject: [PATCH 013/151] Fix serializer module --- .../hep/dataforge/vision/gdml/TestConvertor.kt | 2 +- .../hep/dataforge/vision/solid/SolidManager.kt | 17 ++++++++++++++--- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/visionforge-gdml/src/jvmTest/kotlin/hep/dataforge/vision/gdml/TestConvertor.kt b/visionforge-gdml/src/jvmTest/kotlin/hep/dataforge/vision/gdml/TestConvertor.kt index cf9fb7b4..2dac5a76 100644 --- a/visionforge-gdml/src/jvmTest/kotlin/hep/dataforge/vision/gdml/TestConvertor.kt +++ b/visionforge-gdml/src/jvmTest/kotlin/hep/dataforge/vision/gdml/TestConvertor.kt @@ -1,9 +1,9 @@ package hep.dataforge.vision.gdml import hep.dataforge.vision.solid.encodeToString +import kscience.gdml.GDML import nl.adaptivity.xmlutil.StAXReader import org.junit.jupiter.api.Test -import kscience.gdml.GDML class TestConvertor { diff --git a/visionforge-solid/src/commonMain/kotlin/hep/dataforge/vision/solid/SolidManager.kt b/visionforge-solid/src/commonMain/kotlin/hep/dataforge/vision/solid/SolidManager.kt index 5cc3948c..676ee9ba 100644 --- a/visionforge-solid/src/commonMain/kotlin/hep/dataforge/vision/solid/SolidManager.kt +++ b/visionforge-solid/src/commonMain/kotlin/hep/dataforge/vision/solid/SolidManager.kt @@ -12,9 +12,7 @@ import hep.dataforge.vision.Vision import hep.dataforge.vision.VisionForm import hep.dataforge.vision.VisionManager import hep.dataforge.vision.VisionManager.Companion.VISION_SERIAL_MODULE_TARGET -import kotlinx.serialization.DeserializationStrategy -import kotlinx.serialization.ExperimentalSerializationApi -import kotlinx.serialization.KSerializer +import kotlinx.serialization.* import kotlinx.serialization.json.Json import kotlinx.serialization.modules.* import kotlin.reflect.KClass @@ -114,6 +112,19 @@ public class SolidManager(meta: Meta) : AbstractPlugin(meta) { subclass(SolidLabel.serializer()) subclass(Sphere.serializer()) } + + polymorphic(Solid::class) { + subclass(SolidGroup.serializer()) + subclass(Proxy.serializer()) + subclass(Composite.serializer()) + subclass(Tube.serializer()) + subclass(Box.serializer()) + subclass(Convex.serializer()) + subclass(Extruded.serializer()) + subclass(PolyLine.serializer()) + subclass(SolidLabel.serializer()) + subclass(Sphere.serializer()) + } } val jsonForSolids = Json { From 22c3521a9ec843768ff637eeffa29c49a69c989d Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Wed, 14 Oct 2020 22:20:42 +0300 Subject: [PATCH 014/151] add Dependency structure.vsdx --- doc/Dependency structure.vsdx | Bin 0 -> 26099 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 doc/Dependency structure.vsdx diff --git a/doc/Dependency structure.vsdx b/doc/Dependency structure.vsdx new file mode 100644 index 0000000000000000000000000000000000000000..6c7f1cf651e19f85f4661e91bc35a6623847f2cb GIT binary patch literal 26099 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 Date: Wed, 28 Oct 2020 22:11:28 +0300 Subject: [PATCH 015/151] Remove bootstrap from solid --- build.gradle.kts | 2 +- demo/gdml/build.gradle.kts | 7 ++--- .../vision/gdml/demo/GDMLAppComponent.kt | 29 +++++++++---------- demo/muon-monitor/build.gradle.kts | 2 +- .../mipt/npm/muon/monitor/MMAppComponent.kt | 20 +++++++------ gradle/wrapper/gradle-wrapper.properties | 2 +- settings.gradle.kts | 6 ++-- ui/bootstrap/build.gradle.kts | 1 + .../vision/bootstrap}/outputConfig.kt | 7 ++--- ui/react/build.gradle.kts | 4 +-- .../dataforge/vision/react/ConfigEditor.kt | 19 ++++++------ .../hep/dataforge/vision/react/MetaViewer.kt | 2 +- .../hep/dataforge/vision/react/ObjectTree.kt | 8 ++--- .../hep/dataforge/vision/react/react.kt | 24 ++++----------- visionforge-core/build.gradle.kts | 2 +- visionforge-gdml/build.gradle.kts | 2 +- .../dataforge/vision/gdml/GDMLTransformer.kt | 23 +++++++-------- visionforge-solid/build.gradle.kts | 1 - .../hep/dataforge/vision/solid/ConvexTest.kt | 2 +- .../solid/three/ThreeCanvasComponent.kt | 4 +-- 20 files changed, 75 insertions(+), 92 deletions(-) rename {visionforge-solid/src/jsMain/kotlin/hep/dataforge/vision/solid/three => ui/bootstrap/src/main/kotlin/hep/dataforge/vision/bootstrap}/outputConfig.kt (97%) diff --git a/build.gradle.kts b/build.gradle.kts index f2a94902..bc20d61f 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -4,7 +4,7 @@ plugins { id("ru.mipt.npm.project") } -val dataforgeVersion by extra("0.2.0-dev-3") +val dataforgeVersion by extra("0.2.0-dev-4") val ktorVersion by extra("1.4.1") allprojects { diff --git a/demo/gdml/build.gradle.kts b/demo/gdml/build.gradle.kts index 1824345c..82e03364 100644 --- a/demo/gdml/build.gradle.kts +++ b/demo/gdml/build.gradle.kts @@ -14,11 +14,8 @@ kscience { } kotlin { - jvm { - afterEvaluate { - withJava() - } + withJava() } sourceSets { commonMain { @@ -37,7 +34,7 @@ kotlin { } application { - mainClassName = "hep.dataforge.vision.gdml.demo.GdmlFxDemoAppKt" + mainClass.set("hep.dataforge.vision.gdml.demo.GdmlFxDemoAppKt") } val convertGdmlToJson by tasks.creating(JavaExec::class) { diff --git a/demo/gdml/src/jsMain/kotlin/hep/dataforge/vision/gdml/demo/GDMLAppComponent.kt b/demo/gdml/src/jsMain/kotlin/hep/dataforge/vision/gdml/demo/GDMLAppComponent.kt index 4b9a4e0d..8624f141 100644 --- a/demo/gdml/src/jsMain/kotlin/hep/dataforge/vision/gdml/demo/GDMLAppComponent.kt +++ b/demo/gdml/src/jsMain/kotlin/hep/dataforge/vision/gdml/demo/GDMLAppComponent.kt @@ -9,14 +9,10 @@ import hep.dataforge.vision.bootstrap.* import hep.dataforge.vision.gdml.toVision import hep.dataforge.vision.react.component import hep.dataforge.vision.react.objectTree -import hep.dataforge.vision.react.state import hep.dataforge.vision.solid.Solid import hep.dataforge.vision.solid.SolidGroup -import hep.dataforge.vision.solid.specifications.Camera -import hep.dataforge.vision.solid.specifications.Canvas3DOptions import hep.dataforge.vision.solid.three.ThreeCanvas import hep.dataforge.vision.solid.three.ThreeCanvasComponent -import hep.dataforge.vision.solid.three.canvasControls import kotlinx.browser.window import kotlinx.css.FlexBasis import kotlinx.css.Overflow @@ -28,8 +24,10 @@ import org.w3c.files.FileReader import org.w3c.files.get import react.RProps import react.dom.h1 +import react.getValue +import react.setValue +import react.useState import styled.css -import kotlin.math.PI external interface GDMLAppProps : RProps { var context: Context @@ -37,18 +35,19 @@ external interface GDMLAppProps : RProps { var selected: Name? } -private val canvasConfig = Canvas3DOptions { - camera = Camera { - distance = 2100.0 - latitude = PI / 6 - azimuth = PI + PI / 6 - } -} +//private val canvasConfig = Canvas3DOptions { +// camera = Camera { +// distance = 2100.0 +// latitude = PI / 6 +// azimuth = PI + PI / 6 +// } +//} +@JsExport val GDMLApp = component { props -> - var selected by state { props.selected } - var canvas: ThreeCanvas? by state { null } - var vision: Vision? by state { props.rootObject } + var selected by useState { props.selected } + var canvas: ThreeCanvas? by useState { null } + var vision: Vision? by useState { props.rootObject } val select: (Name?) -> Unit = { selected = it diff --git a/demo/muon-monitor/build.gradle.kts b/demo/muon-monitor/build.gradle.kts index 3e0cb8d9..1f44169d 100644 --- a/demo/muon-monitor/build.gradle.kts +++ b/demo/muon-monitor/build.gradle.kts @@ -55,7 +55,7 @@ kotlin { } application { - mainClassName = "ru.mipt.npm.muon.monitor.server.MMServerKt" + mainClass.set("ru.mipt.npm.muon.monitor.server.MMServerKt") } distributions { diff --git a/demo/muon-monitor/src/jsMain/kotlin/ru/mipt/npm/muon/monitor/MMAppComponent.kt b/demo/muon-monitor/src/jsMain/kotlin/ru/mipt/npm/muon/monitor/MMAppComponent.kt index a4540ebd..d492b325 100644 --- a/demo/muon-monitor/src/jsMain/kotlin/ru/mipt/npm/muon/monitor/MMAppComponent.kt +++ b/demo/muon-monitor/src/jsMain/kotlin/ru/mipt/npm/muon/monitor/MMAppComponent.kt @@ -6,16 +6,15 @@ import hep.dataforge.names.NameToken import hep.dataforge.names.isEmpty import hep.dataforge.names.length import hep.dataforge.vision.Vision +import hep.dataforge.vision.bootstrap.canvasControls import hep.dataforge.vision.bootstrap.card import hep.dataforge.vision.react.component import hep.dataforge.vision.react.configEditor import hep.dataforge.vision.react.objectTree -import hep.dataforge.vision.react.state import hep.dataforge.vision.solid.specifications.Camera import hep.dataforge.vision.solid.specifications.Canvas3DOptions import hep.dataforge.vision.solid.three.ThreeCanvas import hep.dataforge.vision.solid.three.ThreeCanvasComponent -import hep.dataforge.vision.solid.three.canvasControls import io.ktor.client.HttpClient import io.ktor.client.request.get import kotlinx.coroutines.GlobalScope @@ -23,6 +22,9 @@ import kotlinx.coroutines.launch import kotlinx.html.js.onClickFunction import react.RProps import react.dom.* +import react.getValue +import react.setValue +import react.useState import kotlin.math.PI external interface MMAppProps : RProps { @@ -42,14 +44,14 @@ private val canvasConfig = Canvas3DOptions { @JsExport val MMApp = component { props -> - var selected by state { props.selected } - var canvas: ThreeCanvas? by state { null } + var selected by useState { props.selected } + var canvas: ThreeCanvas? by useState { null } val select: (Name?) -> Unit = { selected = it } - val visual = props.model.root + val root = props.model.root div("row") { h1("mx-auto") { @@ -60,7 +62,7 @@ val MMApp = component { props -> div("col-lg-3 px-0 overflow-auto") { //tree card("Object tree") { - objectTree(visual, selected, select) + objectTree(root, selected, select) } } div("col-lg-6") { @@ -68,7 +70,7 @@ val MMApp = component { props -> child(ThreeCanvasComponent::class) { attrs { this.context = props.context - this.obj = visual + this.obj = root this.options = canvasConfig this.selected = selected this.clickCallback = select @@ -153,8 +155,8 @@ val MMApp = component { props -> selected.let { selected -> val selectedObject: Vision? = when { selected == null -> null - selected.isEmpty() -> visual - else -> visual[selected] + selected.isEmpty() -> root + else -> root[selected] } if (selectedObject != null) { configEditor(selectedObject, default = selectedObject.getAllProperties(), key = selected) diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 12d38de6..be52383e 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.6.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/settings.gradle.kts b/settings.gradle.kts index 40fcab11..65690060 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1,9 +1,9 @@ pluginManagement { - val kotlinVersion = "1.4.20-M1" - val toolsVersion = "0.6.3-dev-1.4.20-M1" + val kotlinVersion = "1.4.20-M2" + val toolsVersion = "0.6.4-dev-1.4.20-M2" repositories { - mavenLocal() +// mavenLocal() jcenter() gradlePluginPortal() maven("https://dl.bintray.com/kotlin/kotlin-eap") diff --git a/ui/bootstrap/build.gradle.kts b/ui/bootstrap/build.gradle.kts index b2400d0c..1cdd834d 100644 --- a/ui/bootstrap/build.gradle.kts +++ b/ui/bootstrap/build.gradle.kts @@ -5,5 +5,6 @@ plugins { val dataforgeVersion: String by rootProject.extra dependencies{ + api(project(":visionforge-solid")) api(project(":ui:react")) } \ No newline at end of file diff --git a/visionforge-solid/src/jsMain/kotlin/hep/dataforge/vision/solid/three/outputConfig.kt b/ui/bootstrap/src/main/kotlin/hep/dataforge/vision/bootstrap/outputConfig.kt similarity index 97% rename from visionforge-solid/src/jsMain/kotlin/hep/dataforge/vision/solid/three/outputConfig.kt rename to ui/bootstrap/src/main/kotlin/hep/dataforge/vision/bootstrap/outputConfig.kt index f4e65da1..b6326979 100644 --- a/visionforge-solid/src/jsMain/kotlin/hep/dataforge/vision/solid/three/outputConfig.kt +++ b/ui/bootstrap/src/main/kotlin/hep/dataforge/vision/bootstrap/outputConfig.kt @@ -1,11 +1,11 @@ -package hep.dataforge.vision.solid.three +package hep.dataforge.vision.bootstrap import hep.dataforge.js.requireJS import hep.dataforge.meta.DFExperimental -import hep.dataforge.vision.bootstrap.accordion -import hep.dataforge.vision.bootstrap.entry import hep.dataforge.vision.solid.SolidGroup import hep.dataforge.vision.solid.SolidManager +import hep.dataforge.vision.solid.three.ThreeCanvas +import kotlinx.dom.clear import kotlinx.html.* import kotlinx.html.dom.append import kotlinx.html.js.onChangeFunction @@ -21,7 +21,6 @@ import react.dom.button import react.dom.div import react.dom.input import react.dom.label -import kotlin.dom.clear private fun saveData(event: Event, fileName: String, mimeType: String = "text/plain", dataBuilder: () -> String) { event.stopPropagation(); diff --git a/ui/react/build.gradle.kts b/ui/react/build.gradle.kts index 3fb049b5..8d541ffd 100644 --- a/ui/react/build.gradle.kts +++ b/ui/react/build.gradle.kts @@ -2,13 +2,13 @@ plugins { id("ru.mipt.npm.js") } -val reactVersion by extra("16.13.1") +val reactVersion by extra("17.0.0") dependencies{ api(project(":visionforge-core")) //api("org.jetbrains:kotlin-react:16.13.1-pre.104-kotlin-1.3.72") - api("org.jetbrains:kotlin-react-dom:$reactVersion-pre.123-kotlin-1.4.10") + api("org.jetbrains:kotlin-react-dom:$reactVersion-pre.126-kotlin-1.4.10") api(npm("react", reactVersion)) api(npm("react-dom", reactVersion)) diff --git a/ui/react/src/main/kotlin/hep/dataforge/vision/react/ConfigEditor.kt b/ui/react/src/main/kotlin/hep/dataforge/vision/react/ConfigEditor.kt index 6669f491..8c749d47 100644 --- a/ui/react/src/main/kotlin/hep/dataforge/vision/react/ConfigEditor.kt +++ b/ui/react/src/main/kotlin/hep/dataforge/vision/react/ConfigEditor.kt @@ -42,11 +42,11 @@ private val ConfigEditorItem: FunctionalComponent = compo } private fun RFBuilder.configEditorItem(props: ConfigEditorItemProps) { - var expanded: Boolean by state { true } - var item: MetaItem? by state { props.root[props.name] } + var expanded: Boolean by useState { true } + var item: MetaItem? by useState { props.root[props.name] } val descriptorItem: ItemDescriptor? = props.descriptor?.get(props.name) val defaultItem = props.default?.get(props.name) - var actualItem: MetaItem? by state { item ?: defaultItem ?: descriptorItem?.defaultItem() } + var actualItem: MetaItem? by useState { item ?: defaultItem ?: descriptorItem?.defaultItem() } val token = props.name.lastOrNull()?.toString() ?: "Properties" @@ -191,13 +191,14 @@ private fun RFBuilder.configEditorItem(props: ConfigEditorItemProps) { } public external interface ConfigEditorProps : RProps { - var id: Name - var root: Config - var default: Meta? - var descriptor: NodeDescriptor? + public var id: Name + public var root: Config + public var default: Meta? + public var descriptor: NodeDescriptor? } -val ConfigEditor = component { props -> +@JsExport +public val ConfigEditor: FunctionalComponent = component { props -> child(ConfigEditorItem) { attrs { this.key = "" @@ -209,7 +210,7 @@ val ConfigEditor = component { props -> } } -fun Element.configEditor(config: Config, descriptor: NodeDescriptor? = null, default: Meta? = null, key: Any? = null) { +public fun Element.configEditor(config: Config, descriptor: NodeDescriptor? = null, default: Meta? = null, key: Any? = null) { render(this) { child(ConfigEditor) { attrs { diff --git a/ui/react/src/main/kotlin/hep/dataforge/vision/react/MetaViewer.kt b/ui/react/src/main/kotlin/hep/dataforge/vision/react/MetaViewer.kt index 48e49a19..fbf6dcc5 100644 --- a/ui/react/src/main/kotlin/hep/dataforge/vision/react/MetaViewer.kt +++ b/ui/react/src/main/kotlin/hep/dataforge/vision/react/MetaViewer.kt @@ -39,7 +39,7 @@ private val MetaViewerItem: FunctionalComponent = component { p } private fun RFBuilder.metaViewerItem(props: MetaViewerProps) { - var expanded: Boolean by state { true } + var expanded: Boolean by useState { true } val item = props.root[props.name] val descriptorItem: ItemDescriptor? = props.descriptor?.get(props.name) val actualItem = item ?: descriptorItem?.defaultItem() diff --git a/ui/react/src/main/kotlin/hep/dataforge/vision/react/ObjectTree.kt b/ui/react/src/main/kotlin/hep/dataforge/vision/react/ObjectTree.kt index 91760b4a..053569d7 100644 --- a/ui/react/src/main/kotlin/hep/dataforge/vision/react/ObjectTree.kt +++ b/ui/react/src/main/kotlin/hep/dataforge/vision/react/ObjectTree.kt @@ -13,10 +13,10 @@ import react.* import styled.* public external interface ObjectTreeProps : RProps { - var name: Name - var selected: Name? - var obj: Vision - var clickCallback: (Name) -> Unit + public var name: Name + public var selected: Name? + public var obj: Vision + public var clickCallback: (Name) -> Unit } private fun RFBuilder.objectTree(props: ObjectTreeProps): Unit { diff --git a/ui/react/src/main/kotlin/hep/dataforge/vision/react/react.kt b/ui/react/src/main/kotlin/hep/dataforge/vision/react/react.kt index 718a21b7..a0e2c787 100644 --- a/ui/react/src/main/kotlin/hep/dataforge/vision/react/react.kt +++ b/ui/react/src/main/kotlin/hep/dataforge/vision/react/react.kt @@ -1,16 +1,14 @@ package hep.dataforge.vision.react import react.* -import kotlin.properties.ReadWriteProperty -import kotlin.reflect.KProperty -class RFBuilder : RBuilder() +public class RFBuilder : RBuilder() /** * Get functional component from [func] */ -fun

component( - func: RFBuilder.(props: P) -> Unit +public inline fun

component( + crossinline func: RFBuilder.(props: P) -> Unit, ): FunctionalComponent

{ return { props: P -> val nodes = RFBuilder().apply { func(props) }.childList @@ -21,18 +19,6 @@ fun

component( } } } - -fun RFBuilder.state(init: () -> T): ReadWriteProperty = - object : ReadWriteProperty { - val pair = react.useState(init) - override fun getValue(thisRef: Any?, property: KProperty<*>): T { - return pair.first - } - - override fun setValue(thisRef: Any?, property: KProperty<*>, value: T) { - pair.second(value) - } - } - -fun RFBuilder.memoize(vararg deps: dynamic, builder: () -> T): T = useMemo(builder, deps) +// +//public fun RFBuilder.memoize(vararg deps: dynamic, builder: () -> T): T = useMemo(builder, deps) diff --git a/visionforge-core/build.gradle.kts b/visionforge-core/build.gradle.kts index 546587d2..2bf0b6e0 100644 --- a/visionforge-core/build.gradle.kts +++ b/visionforge-core/build.gradle.kts @@ -31,7 +31,7 @@ kotlin { //api("org.jetbrains:kotlin-extensions:1.0.1-pre.105-kotlin-1.3.72") //api("org.jetbrains:kotlin-css-js:1.0.0-pre.105-kotlin-1.3.72") - api("org.jetbrains:kotlin-styled:5.2.0-pre.123-kotlin-1.4.10") + api("org.jetbrains:kotlin-styled:5.2.0-pre.126-kotlin-1.4.10") api(npm("core-js", "2.6.5")) api(npm("inline-style-prefixer", "5.1.0")) diff --git a/visionforge-gdml/build.gradle.kts b/visionforge-gdml/build.gradle.kts index ebb6a865..d6456b16 100644 --- a/visionforge-gdml/build.gradle.kts +++ b/visionforge-gdml/build.gradle.kts @@ -7,7 +7,7 @@ kotlin { val commonMain by getting { dependencies { api(project(":visionforge-solid")) - api("kscience.gdml:gdml:0.2.0-dev-2") + api("kscience.gdml:gdml:0.2.0-dev-3") } } } diff --git a/visionforge-gdml/src/commonMain/kotlin/hep/dataforge/vision/gdml/GDMLTransformer.kt b/visionforge-gdml/src/commonMain/kotlin/hep/dataforge/vision/gdml/GDMLTransformer.kt index 3995c92f..1374f70f 100644 --- a/visionforge-gdml/src/commonMain/kotlin/hep/dataforge/vision/gdml/GDMLTransformer.kt +++ b/visionforge-gdml/src/commonMain/kotlin/hep/dataforge/vision/gdml/GDMLTransformer.kt @@ -7,7 +7,6 @@ import hep.dataforge.names.Name import hep.dataforge.names.asName import hep.dataforge.names.plus import hep.dataforge.names.toName -import hep.dataforge.vision.MutableVisionGroup import hep.dataforge.vision.set import hep.dataforge.vision.solid.* import hep.dataforge.vision.solid.SolidMaterial.Companion.MATERIAL_COLOR_KEY @@ -20,21 +19,21 @@ import kotlin.random.Random private val solidsName = "solids".asName() private val volumesName = "volumes".asName() -public class GDMLTransformer internal constructor(val root: GDML) { +public class GDMLTransformer internal constructor(public val root: GDML) { //private val materialCache = HashMap() private val random = Random(222) - enum class Action { + public enum class Action { ADD, REJECT, PROTOTYPE } - var lUnit: LUnit = LUnit.MM - var aUnit: AUnit = AUnit.RADIAN + public var lUnit: LUnit = LUnit.MM + public var aUnit: AUnit = AUnit.RADIAN - var solidAction: (GDMLSolid) -> Action = { Action.PROTOTYPE } - var volumeAction: (GDMLGroup) -> Action = { Action.PROTOTYPE } + public var solidAction: (GDMLSolid) -> Action = { Action.PROTOTYPE } + public var volumeAction: (GDMLGroup) -> Action = { Action.PROTOTYPE } /** * A special group for local templates @@ -71,7 +70,7 @@ public class GDMLTransformer internal constructor(val root: GDML) { private val styleCache = HashMap() - var solidConfiguration: Solid.(parent: GDMLVolume, solid: GDMLSolid) -> Unit = { parent, _ -> + public var solidConfiguration: Solid.(parent: GDMLVolume, solid: GDMLSolid) -> Unit = { parent, _ -> lUnit = LUnit.CM if (parent.physVolumes.isNotEmpty()) { useStyle("opaque") { @@ -101,7 +100,7 @@ public class GDMLTransformer internal constructor(val root: GDML) { obj.solidConfiguration(parent, solid) } - var onFinish: GDMLTransformer.() -> Unit = {} + public var onFinish: GDMLTransformer.() -> Unit = {} private fun T.withPosition( @@ -356,13 +355,13 @@ public class GDMLTransformer internal constructor(val root: GDML) { return final } - val result by lazy { + public val result: SolidGroup by lazy { finalize(volume(root.world)) } } -fun GDML.toVision(block: GDMLTransformer.() -> Unit = {}): SolidGroup { +public fun GDML.toVision(block: GDMLTransformer.() -> Unit = {}): SolidGroup { val context = GDMLTransformer(this).apply(block) return context.result } @@ -370,7 +369,7 @@ fun GDML.toVision(block: GDMLTransformer.() -> Unit = {}): SolidGroup { /** * Append gdml node to the group */ -fun SolidGroup.gdml(gdml: GDML, key: String = "", transformer: GDMLTransformer.() -> Unit = {}) { +public fun SolidGroup.gdml(gdml: GDML, key: String = "", transformer: GDMLTransformer.() -> Unit = {}) { val visual = gdml.toVision(transformer) //println(Visual3DPlugin.json.stringify(VisualGroup3D.serializer(), visual)) set(key, visual) diff --git a/visionforge-solid/build.gradle.kts b/visionforge-solid/build.gradle.kts index 7f08e038..aab7e547 100644 --- a/visionforge-solid/build.gradle.kts +++ b/visionforge-solid/build.gradle.kts @@ -29,7 +29,6 @@ kotlin { } jsMain { dependencies { - implementation(project(":ui:bootstrap"))//to be removed later implementation(npm("three", "0.114.0")) implementation(npm("three-csg-ts", "1.0.1")) api(npm("file-saver", "2.0.2")) diff --git a/visionforge-solid/src/commonTest/kotlin/hep/dataforge/vision/solid/ConvexTest.kt b/visionforge-solid/src/commonTest/kotlin/hep/dataforge/vision/solid/ConvexTest.kt index 7da077bd..d2dbc4b3 100644 --- a/visionforge-solid/src/commonTest/kotlin/hep/dataforge/vision/solid/ConvexTest.kt +++ b/visionforge-solid/src/commonTest/kotlin/hep/dataforge/vision/solid/ConvexTest.kt @@ -1,7 +1,7 @@ package hep.dataforge.vision.solid import hep.dataforge.meta.* -import kotlinx.serialization.json.toJson + import kotlin.test.Test import kotlin.test.assertEquals diff --git a/visionforge-solid/src/jsMain/kotlin/hep/dataforge/vision/solid/three/ThreeCanvasComponent.kt b/visionforge-solid/src/jsMain/kotlin/hep/dataforge/vision/solid/three/ThreeCanvasComponent.kt index fbc90a62..ee033817 100644 --- a/visionforge-solid/src/jsMain/kotlin/hep/dataforge/vision/solid/three/ThreeCanvasComponent.kt +++ b/visionforge-solid/src/jsMain/kotlin/hep/dataforge/vision/solid/three/ThreeCanvasComponent.kt @@ -28,7 +28,7 @@ public external interface ThreeCanvasState : RState { } @JsExport -class ThreeCanvasComponent : RComponent() { +public class ThreeCanvasComponent : RComponent() { private var canvas: ThreeCanvas? = null @@ -62,7 +62,7 @@ class ThreeCanvasComponent : RComponent() { } } -fun RBuilder.threeCanvas(object3D: Solid, options: Canvas3DOptions.() -> Unit = {}) { +public fun RBuilder.threeCanvas(object3D: Solid, options: Canvas3DOptions.() -> Unit = {}) { child(ThreeCanvasComponent::class) { attrs { this.obj = object3D From aaad8365677118fb6e7e93eb839993d11c5731e5 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Fri, 30 Oct 2020 10:02:49 +0300 Subject: [PATCH 016/151] Refactor react ThreeCanvas to functional component --- .../vision/gdml/demo/GDMLAppComponent.kt | 26 ++-- .../mipt/npm/muon/monitor/MMAppComponent.kt | 21 ++-- playground/src/jsMain/kotlin/PlayGroundApp.kt | 21 +++- .../dataforge/vision/react/ConfigEditor.kt | 18 +-- .../hep/dataforge/vision/react/MetaViewer.kt | 14 +-- .../hep/dataforge/vision/react/ObjectTree.kt | 6 +- .../hep/dataforge/vision/react/TreeStyles.kt | 6 +- .../hep/dataforge/vision/react/layout.kt | 5 +- .../hep/dataforge/vision/react/react.kt | 24 ---- .../dataforge/vision/gdml/GdmlOptimizer.kt | 6 +- .../hep/dataforge/vision/gdml/gdmlJs.kt | 6 +- .../hep/dataforge/vision/gdml/gdmlJVM.kt | 2 +- .../vision/solid/three/ThreeCanvas.kt | 45 ++++--- .../solid/three/ThreeCanvasComponent.kt | 111 +++++++++++------- 14 files changed, 162 insertions(+), 149 deletions(-) delete mode 100644 ui/react/src/main/kotlin/hep/dataforge/vision/react/react.kt diff --git a/demo/gdml/src/jsMain/kotlin/hep/dataforge/vision/gdml/demo/GDMLAppComponent.kt b/demo/gdml/src/jsMain/kotlin/hep/dataforge/vision/gdml/demo/GDMLAppComponent.kt index 8624f141..f5704cb7 100644 --- a/demo/gdml/src/jsMain/kotlin/hep/dataforge/vision/gdml/demo/GDMLAppComponent.kt +++ b/demo/gdml/src/jsMain/kotlin/hep/dataforge/vision/gdml/demo/GDMLAppComponent.kt @@ -7,7 +7,6 @@ import hep.dataforge.vision.Vision import hep.dataforge.vision.VisionGroup import hep.dataforge.vision.bootstrap.* import hep.dataforge.vision.gdml.toVision -import hep.dataforge.vision.react.component import hep.dataforge.vision.react.objectTree import hep.dataforge.vision.solid.Solid import hep.dataforge.vision.solid.SolidGroup @@ -22,11 +21,8 @@ import kscience.gdml.GDML import kscience.gdml.decodeFromString import org.w3c.files.FileReader import org.w3c.files.get -import react.RProps +import react.* import react.dom.h1 -import react.getValue -import react.setValue -import react.useState import styled.css external interface GDMLAppProps : RProps { @@ -44,7 +40,7 @@ external interface GDMLAppProps : RProps { //} @JsExport -val GDMLApp = component { props -> +val GDMLApp = functionalComponent("GDMLApp") { props -> var selected by useState { props.selected } var canvas: ThreeCanvas? by useState { null } var vision: Vision? by useState { props.rootObject } @@ -113,16 +109,14 @@ val GDMLApp = component { props -> +"order-xl-2" } //canvas - (vision as? Solid)?.let { visual3D -> - child(ThreeCanvasComponent::class) { - attrs { - this.context = props.context - this.obj = visual3D - this.selected = selected - this.clickCallback = select - this.canvasCallback = { - canvas = it - } + child(ThreeCanvasComponent) { + attrs { + this.context = props.context + this.obj = vision as? Solid + this.selected = selected + this.clickCallback = select + this.canvasCallback = { + canvas = it } } } diff --git a/demo/muon-monitor/src/jsMain/kotlin/ru/mipt/npm/muon/monitor/MMAppComponent.kt b/demo/muon-monitor/src/jsMain/kotlin/ru/mipt/npm/muon/monitor/MMAppComponent.kt index d492b325..527c2b77 100644 --- a/demo/muon-monitor/src/jsMain/kotlin/ru/mipt/npm/muon/monitor/MMAppComponent.kt +++ b/demo/muon-monitor/src/jsMain/kotlin/ru/mipt/npm/muon/monitor/MMAppComponent.kt @@ -8,7 +8,6 @@ import hep.dataforge.names.length import hep.dataforge.vision.Vision import hep.dataforge.vision.bootstrap.canvasControls import hep.dataforge.vision.bootstrap.card -import hep.dataforge.vision.react.component import hep.dataforge.vision.react.configEditor import hep.dataforge.vision.react.objectTree import hep.dataforge.vision.solid.specifications.Camera @@ -20,11 +19,10 @@ import io.ktor.client.request.get import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.launch import kotlinx.html.js.onClickFunction -import react.RProps +import react.* import react.dom.* -import react.getValue -import react.setValue -import react.useState +import styled.css +import styled.styledDiv import kotlin.math.PI external interface MMAppProps : RProps { @@ -43,8 +41,8 @@ private val canvasConfig = Canvas3DOptions { } @JsExport -val MMApp = component { props -> - var selected by useState { props.selected } +val MMApp = functionalComponent("Muon monitor") { props -> + var selected by useState { props.selected } var canvas: ThreeCanvas? by useState { null } val select: (Name?) -> Unit = { @@ -59,7 +57,12 @@ val MMApp = component { props -> } } div("row") { - div("col-lg-3 px-0 overflow-auto") { + styledDiv { + css { + +"col-lg-3" + +"px-0" + +"overflow-auto" + } //tree card("Object tree") { objectTree(root, selected, select) @@ -67,7 +70,7 @@ val MMApp = component { props -> } div("col-lg-6") { //canvas - child(ThreeCanvasComponent::class) { + child(ThreeCanvasComponent) { attrs { this.context = props.context this.obj = root diff --git a/playground/src/jsMain/kotlin/PlayGroundApp.kt b/playground/src/jsMain/kotlin/PlayGroundApp.kt index ea95c926..72196672 100644 --- a/playground/src/jsMain/kotlin/PlayGroundApp.kt +++ b/playground/src/jsMain/kotlin/PlayGroundApp.kt @@ -3,16 +3,25 @@ import hep.dataforge.js.Application import hep.dataforge.js.startApplication import hep.dataforge.vision.bootstrap.visionPropertyEditor import hep.dataforge.vision.react.objectTree -import hep.dataforge.vision.solid.Point3D -import hep.dataforge.vision.solid.SolidGroup -import hep.dataforge.vision.solid.box -import hep.dataforge.vision.solid.group +import hep.dataforge.vision.solid.* +import hep.dataforge.vision.solid.specifications.Canvas3DOptions +import hep.dataforge.vision.solid.three.ThreeCanvasComponent import hep.dataforge.vision.solid.three.ThreePlugin -import hep.dataforge.vision.solid.three.threeCanvas +import kotlinx.browser.document import org.w3c.dom.HTMLElement +import react.RBuilder +import react.child import react.dom.div import react.dom.render -import kotlin.browser.document + +public fun RBuilder.threeCanvas(object3D: Solid, options: Canvas3DOptions.() -> Unit = {}) { + child(ThreeCanvasComponent) { + attrs { + this.obj = object3D + this.options = Canvas3DOptions.invoke(options) + } + } +} private class PlayGroundApp : Application { diff --git a/ui/react/src/main/kotlin/hep/dataforge/vision/react/ConfigEditor.kt b/ui/react/src/main/kotlin/hep/dataforge/vision/react/ConfigEditor.kt index 8c749d47..9d9078f7 100644 --- a/ui/react/src/main/kotlin/hep/dataforge/vision/react/ConfigEditor.kt +++ b/ui/react/src/main/kotlin/hep/dataforge/vision/react/ConfigEditor.kt @@ -19,29 +19,29 @@ public external interface ConfigEditorItemProps : RProps { /** * Root config object - always non null */ - var root: Config + public var root: Config /** * Full path to the displayed node in [root]. Could be empty */ - var name: Name + public var name: Name /** * Root default */ - var default: Meta? + public var default: Meta? /** * Root descriptor */ - var descriptor: NodeDescriptor? + public var descriptor: NodeDescriptor? } -private val ConfigEditorItem: FunctionalComponent = component { props -> +private val ConfigEditorItem: FunctionalComponent = functionalComponent("ConfigEditorItem") { props -> configEditorItem(props) } -private fun RFBuilder.configEditorItem(props: ConfigEditorItemProps) { +private fun RBuilder.configEditorItem(props: ConfigEditorItemProps) { var expanded: Boolean by useState { true } var item: MetaItem? by useState { props.root[props.name] } val descriptorItem: ItemDescriptor? = props.descriptor?.get(props.name) @@ -198,7 +198,7 @@ public external interface ConfigEditorProps : RProps { } @JsExport -public val ConfigEditor: FunctionalComponent = component { props -> +public val ConfigEditor: FunctionalComponent = functionalComponent("ConfigEditor") { props -> child(ConfigEditorItem) { attrs { this.key = "" @@ -223,7 +223,7 @@ public fun Element.configEditor(config: Config, descriptor: NodeDescriptor? = nu } } -fun RBuilder.configEditor(config: Config, descriptor: NodeDescriptor? = null, default: Meta? = null, key: Any? = null) { +public fun RBuilder.configEditor(config: Config, descriptor: NodeDescriptor? = null, default: Meta? = null, key: Any? = null) { child(ConfigEditor) { attrs { this.key = key?.toString() ?: "" @@ -234,7 +234,7 @@ fun RBuilder.configEditor(config: Config, descriptor: NodeDescriptor? = null, de } } -fun RBuilder.configEditor( +public fun RBuilder.configEditor( obj: Configurable, descriptor: NodeDescriptor? = obj.descriptor, default: Meta? = null, diff --git a/ui/react/src/main/kotlin/hep/dataforge/vision/react/MetaViewer.kt b/ui/react/src/main/kotlin/hep/dataforge/vision/react/MetaViewer.kt index fbf6dcc5..9c17206d 100644 --- a/ui/react/src/main/kotlin/hep/dataforge/vision/react/MetaViewer.kt +++ b/ui/react/src/main/kotlin/hep/dataforge/vision/react/MetaViewer.kt @@ -21,24 +21,24 @@ public external interface MetaViewerProps : RProps { /** * Root meta */ - var root: Meta + public var root: Meta /** * Full path to the displayed node in [root]. Could be empty */ - var name: Name + public var name: Name /** * Root descriptor */ - var descriptor: NodeDescriptor? + public var descriptor: NodeDescriptor? } -private val MetaViewerItem: FunctionalComponent = component { props -> +private val MetaViewerItem: FunctionalComponent = functionalComponent("MetaViewerItem") { props -> metaViewerItem(props) } -private fun RFBuilder.metaViewerItem(props: MetaViewerProps) { +private fun RBuilder.metaViewerItem(props: MetaViewerProps) { var expanded: Boolean by useState { true } val item = props.root[props.name] val descriptorItem: ItemDescriptor? = props.descriptor?.get(props.name) @@ -137,7 +137,7 @@ private fun RFBuilder.metaViewerItem(props: MetaViewerProps) { } @JsExport -val MetaViewer = component { props -> +public val MetaViewer:FunctionalComponent = functionalComponent("MetaViewer") { props -> child(MetaViewerItem) { attrs { this.key = "" @@ -148,7 +148,7 @@ val MetaViewer = component { props -> } } -fun RBuilder.metaViewer(meta: Meta, descriptor: NodeDescriptor? = null, key: Any? = null) { +public fun RBuilder.metaViewer(meta: Meta, descriptor: NodeDescriptor? = null, key: Any? = null) { child(MetaViewer) { attrs { this.key = key?.toString() ?: "" diff --git a/ui/react/src/main/kotlin/hep/dataforge/vision/react/ObjectTree.kt b/ui/react/src/main/kotlin/hep/dataforge/vision/react/ObjectTree.kt index 053569d7..5faab7ba 100644 --- a/ui/react/src/main/kotlin/hep/dataforge/vision/react/ObjectTree.kt +++ b/ui/react/src/main/kotlin/hep/dataforge/vision/react/ObjectTree.kt @@ -19,7 +19,7 @@ public external interface ObjectTreeProps : RProps { public var clickCallback: (Name) -> Unit } -private fun RFBuilder.objectTree(props: ObjectTreeProps): Unit { +private fun RBuilder.objectTree(props: ObjectTreeProps): Unit { var expanded: Boolean by useState { props.selected?.startsWith(props.name) ?: false } val onClick: (Event) -> Unit = { @@ -103,11 +103,11 @@ private fun RFBuilder.objectTree(props: ObjectTreeProps): Unit { } @JsExport -val ObjectTree: FunctionalComponent = component { props -> +public val ObjectTree: FunctionalComponent = functionalComponent("ObjectTree") { props -> objectTree(props) } -fun RBuilder.objectTree( +public fun RBuilder.objectTree( vision: Vision, selected: Name? = null, clickCallback: (Name) -> Unit = {} diff --git a/ui/react/src/main/kotlin/hep/dataforge/vision/react/TreeStyles.kt b/ui/react/src/main/kotlin/hep/dataforge/vision/react/TreeStyles.kt index ead7d577..7cfb7d48 100644 --- a/ui/react/src/main/kotlin/hep/dataforge/vision/react/TreeStyles.kt +++ b/ui/react/src/main/kotlin/hep/dataforge/vision/react/TreeStyles.kt @@ -4,11 +4,11 @@ import kotlinx.css.* import kotlinx.css.properties.* import styled.StyleSheet -object TreeStyles : StyleSheet("treeStyles", true) { +public object TreeStyles : StyleSheet("treeStyles", true) { /** * Remove default bullets */ - val tree by css { + public val tree by css { paddingLeft = 8.px marginLeft = 0.px listStyleType = ListStyleType.none @@ -17,7 +17,7 @@ object TreeStyles : StyleSheet("treeStyles", true) { /** * Style the caret/arrow */ - val treeCaret by css { + public val treeCaret by css { cursor = Cursor.pointer userSelect = UserSelect.none /* Create the caret/arrow with a unicode, and style it */ diff --git a/ui/react/src/main/kotlin/hep/dataforge/vision/react/layout.kt b/ui/react/src/main/kotlin/hep/dataforge/vision/react/layout.kt index 5a13a089..cdafb527 100644 --- a/ui/react/src/main/kotlin/hep/dataforge/vision/react/layout.kt +++ b/ui/react/src/main/kotlin/hep/dataforge/vision/react/layout.kt @@ -6,11 +6,12 @@ import kotlinx.css.display import kotlinx.css.flexDirection import kotlinx.html.DIV import react.RBuilder +import react.ReactElement import styled.StyledDOMBuilder import styled.css import styled.styledDiv -inline fun RBuilder.flexColumn(block: StyledDOMBuilder

.() -> Unit) = +public inline fun RBuilder.flexColumn(block: StyledDOMBuilder
.() -> Unit): ReactElement = styledDiv { css { display = Display.flex @@ -19,7 +20,7 @@ inline fun RBuilder.flexColumn(block: StyledDOMBuilder
.() -> Unit) = block() } -inline fun RBuilder.flexRow(block: StyledDOMBuilder
.() -> Unit) = +public inline fun RBuilder.flexRow(block: StyledDOMBuilder
.() -> Unit): ReactElement = styledDiv { css { display = Display.flex diff --git a/ui/react/src/main/kotlin/hep/dataforge/vision/react/react.kt b/ui/react/src/main/kotlin/hep/dataforge/vision/react/react.kt deleted file mode 100644 index a0e2c787..00000000 --- a/ui/react/src/main/kotlin/hep/dataforge/vision/react/react.kt +++ /dev/null @@ -1,24 +0,0 @@ -package hep.dataforge.vision.react - -import react.* - -public class RFBuilder : RBuilder() - -/** - * Get functional component from [func] - */ -public inline fun

component( - crossinline func: RFBuilder.(props: P) -> Unit, -): FunctionalComponent

{ - return { props: P -> - val nodes = RFBuilder().apply { func(props) }.childList - when (nodes.size) { - 0 -> null - 1 -> nodes.first() - else -> createElement(Fragment, kotlinext.js.js {}, *nodes.toTypedArray()) - } - } -} -// -//public fun RFBuilder.memoize(vararg deps: dynamic, builder: () -> T): T = useMemo(builder, deps) - diff --git a/visionforge-gdml/src/commonMain/kotlin/hep/dataforge/vision/gdml/GdmlOptimizer.kt b/visionforge-gdml/src/commonMain/kotlin/hep/dataforge/vision/gdml/GdmlOptimizer.kt index dba7e32f..692c334b 100644 --- a/visionforge-gdml/src/commonMain/kotlin/hep/dataforge/vision/gdml/GdmlOptimizer.kt +++ b/visionforge-gdml/src/commonMain/kotlin/hep/dataforge/vision/gdml/GdmlOptimizer.kt @@ -13,9 +13,9 @@ import kotlinx.coroutines.Job import kotlinx.coroutines.coroutineScope import mu.KotlinLogging -expect class Counter() { - fun get(): Int - fun incrementAndGet(): Int +public expect class Counter() { + public fun get(): Int + public fun incrementAndGet(): Int } private fun Point3D?.safePlus(other: Point3D?): Point3D? = if (this == null && other == null) { diff --git a/visionforge-gdml/src/jsMain/kotlin/hep/dataforge/vision/gdml/gdmlJs.kt b/visionforge-gdml/src/jsMain/kotlin/hep/dataforge/vision/gdml/gdmlJs.kt index 44a36b6c..87b0f63c 100644 --- a/visionforge-gdml/src/jsMain/kotlin/hep/dataforge/vision/gdml/gdmlJs.kt +++ b/visionforge-gdml/src/jsMain/kotlin/hep/dataforge/vision/gdml/gdmlJs.kt @@ -1,8 +1,8 @@ package hep.dataforge.vision.gdml -actual class Counter { +public actual class Counter { private var count: Int = 0 - actual fun get(): Int = count + public actual fun get(): Int = count - actual fun incrementAndGet(): Int = count++ + public actual fun incrementAndGet(): Int = count++ } \ No newline at end of file diff --git a/visionforge-gdml/src/jvmMain/kotlin/hep/dataforge/vision/gdml/gdmlJVM.kt b/visionforge-gdml/src/jvmMain/kotlin/hep/dataforge/vision/gdml/gdmlJVM.kt index ab58deb9..685708da 100644 --- a/visionforge-gdml/src/jvmMain/kotlin/hep/dataforge/vision/gdml/gdmlJVM.kt +++ b/visionforge-gdml/src/jvmMain/kotlin/hep/dataforge/vision/gdml/gdmlJVM.kt @@ -7,7 +7,7 @@ import java.nio.file.Files import java.nio.file.Path import java.util.concurrent.atomic.AtomicInteger -actual typealias Counter = AtomicInteger +public actual typealias Counter = AtomicInteger fun GDML.Companion.readFile(file: Path): GDML { val xmlReader = StAXReader(Files.newInputStream(file), "UTF-8") diff --git a/visionforge-solid/src/jsMain/kotlin/hep/dataforge/vision/solid/three/ThreeCanvas.kt b/visionforge-solid/src/jsMain/kotlin/hep/dataforge/vision/solid/three/ThreeCanvas.kt index a4e44f35..72db7ba4 100644 --- a/visionforge-solid/src/jsMain/kotlin/hep/dataforge/vision/solid/three/ThreeCanvas.kt +++ b/visionforge-solid/src/jsMain/kotlin/hep/dataforge/vision/solid/three/ThreeCanvas.kt @@ -29,11 +29,11 @@ import info.laht.threekt.math.Vector2 import info.laht.threekt.objects.LineSegments import info.laht.threekt.objects.Mesh import info.laht.threekt.scenes.Scene +import kotlinx.browser.window +import kotlinx.dom.clear import org.w3c.dom.HTMLElement import org.w3c.dom.Node import org.w3c.dom.events.MouseEvent -import kotlin.browser.window -import kotlin.dom.clear import kotlin.math.cos import kotlin.math.max import kotlin.math.sin @@ -41,11 +41,16 @@ import kotlin.math.sin /** * */ -class ThreeCanvas(element: HTMLElement, val three: ThreePlugin, val options: Canvas3DOptions) : Renderer { +public class ThreeCanvas( + element: HTMLElement, + public val three: ThreePlugin, + public val options: Canvas3DOptions, + public val onClick: ((Name?) -> Unit)? = null, +) : Renderer { override val context: Context get() = three.context - var content: Solid? = null + public var content: Solid? = null private set private var root: Object3D? = null @@ -53,17 +58,15 @@ class ThreeCanvas(element: HTMLElement, val three: ThreePlugin, val options: Can private val raycaster = Raycaster() private val mousePosition: Vector2 = Vector2() - var onClick: ((Name?) -> Unit)? = null - - val axes = AxesHelper(options.axes.size.toInt()).apply { + public val axes: AxesHelper = AxesHelper(options.axes.size.toInt()).apply { visible = options.axes.visible } - val scene: Scene = Scene().apply { + public val scene: Scene = Scene().apply { add(axes) } - val camera = buildCamera(options.camera) + public val camera: PerspectiveCamera = buildCamera(options.camera) private var picked: Object3D? = null @@ -166,7 +169,7 @@ class ThreeCanvas(element: HTMLElement, val three: ThreePlugin, val options: Can } } - fun clear() { + public fun clear() { scene.children.find { it.name == "@root" }?.let { scene.remove(it) } @@ -192,7 +195,7 @@ class ThreeCanvas(element: HTMLElement, val three: ThreePlugin, val options: Can private fun Object3D.toggleHighlight( highlight: Boolean, edgesName: String, - material: LineBasicMaterial = SELECTED_MATERIAL + material: LineBasicMaterial = SELECTED_MATERIAL, ) { if (userData[DO_NOT_HIGHLIGHT_TAG] == true) { return @@ -220,7 +223,7 @@ class ThreeCanvas(element: HTMLElement, val three: ThreePlugin, val options: Can /** * Toggle highlight for element with given name */ - fun select(name: Name?) { + public fun select(name: Name?) { if (name == null) { selected?.toggleHighlight(false, SELECT_NAME, SELECTED_MATERIAL) selected = null @@ -234,15 +237,21 @@ class ThreeCanvas(element: HTMLElement, val three: ThreePlugin, val options: Can } } - companion object { - const val DO_NOT_HIGHLIGHT_TAG = "doNotHighlight" + public companion object { + public const val DO_NOT_HIGHLIGHT_TAG = "doNotHighlight" private const val HIGHLIGHT_NAME = "@highlight" private const val SELECT_NAME = "@select" } } -fun ThreePlugin.output(element: HTMLElement, spec: Canvas3DOptions = Canvas3DOptions.empty()): ThreeCanvas = - ThreeCanvas(element, this, spec) +public fun ThreePlugin.output( + element: HTMLElement, + spec: Canvas3DOptions = Canvas3DOptions.empty(), + onClick: ((Name?) -> Unit)? = null, +): ThreeCanvas = ThreeCanvas(element, this, spec, onClick) -fun ThreePlugin.render(element: HTMLElement, obj: Solid, spec: Canvas3DOptions = Canvas3DOptions.empty()): Unit = - output(element, spec).render(obj) \ No newline at end of file +public fun ThreePlugin.render( + element: HTMLElement, obj: Solid, + spec: Canvas3DOptions = Canvas3DOptions.empty(), + onClick: ((Name?) -> Unit)? = null, +): Unit = output(element, spec, onClick).render(obj) \ No newline at end of file diff --git a/visionforge-solid/src/jsMain/kotlin/hep/dataforge/vision/solid/three/ThreeCanvasComponent.kt b/visionforge-solid/src/jsMain/kotlin/hep/dataforge/vision/solid/three/ThreeCanvasComponent.kt index ee033817..9f335642 100644 --- a/visionforge-solid/src/jsMain/kotlin/hep/dataforge/vision/solid/three/ThreeCanvasComponent.kt +++ b/visionforge-solid/src/jsMain/kotlin/hep/dataforge/vision/solid/three/ThreeCanvasComponent.kt @@ -6,67 +6,88 @@ import hep.dataforge.vision.solid.Solid import hep.dataforge.vision.solid.specifications.Canvas3DOptions import org.w3c.dom.Element import org.w3c.dom.HTMLElement -import react.RBuilder -import react.RComponent -import react.RProps -import react.RState +import react.* import react.dom.div -import react.dom.findDOMNode public external interface ThreeCanvasProps : RProps { - var context: Context - var obj: Solid - var options: Canvas3DOptions? - var selected: Name? - var clickCallback: (Name?) -> Unit - var canvasCallback: ((ThreeCanvas?) -> Unit)? + public var context: Context + public var obj: Solid? + public var options: Canvas3DOptions? + public var selected: Name? + public var clickCallback: (Name?) -> Unit + public var canvasCallback: ((ThreeCanvas?) -> Unit)? } public external interface ThreeCanvasState : RState { - var element: Element? + public var element: Element? // var canvas: ThreeCanvas? } -@JsExport -public class ThreeCanvasComponent : RComponent() { +public val ThreeCanvasComponent: FunctionalComponent = functionalComponent( + "ThreeCanvasComponent" +) { props -> + val elementRef = useRef(null) + var canvas by useState(null) - private var canvas: ThreeCanvas? = null - - override fun componentDidMount() { - if(canvas == null) { - val element = state.element as? HTMLElement ?: error("Canvas element not found") + useEffect(listOf(props.context, props.obj, props.options, elementRef)) { + if (canvas == null) { + val element = elementRef.current as? HTMLElement ?: error("Canvas element not found") val three: ThreePlugin = props.context.plugins.fetch(ThreePlugin) - canvas = three.output(element, props.options ?: Canvas3DOptions.empty()).apply { - onClick = props.clickCallback - } - props.canvasCallback?.invoke(canvas) - } - canvas?.render(props.obj) - } - - override fun componentDidUpdate(prevProps: ThreeCanvasProps, prevState: ThreeCanvasState, snapshot: Any) { - if (prevProps.obj != props.obj) { - componentDidMount() - } - if (prevProps.selected != props.selected) { - canvas?.select(props.selected) + val newCanvas = three.output(element, props.options ?: Canvas3DOptions.empty(), props.clickCallback) + props.canvasCallback?.invoke(newCanvas) + canvas = newCanvas } } - override fun RBuilder.render() { - div { - ref { - state.element = findDOMNode(it) + useEffect(listOf(canvas, props.obj)) { + props.obj?.let { obj -> + if (canvas?.content != obj) { + canvas?.render(obj) } } } + + useEffect(listOf(canvas, props.selected)) { + canvas?.select(props.selected) + } + + div { + ref = elementRef + } } -public fun RBuilder.threeCanvas(object3D: Solid, options: Canvas3DOptions.() -> Unit = {}) { - child(ThreeCanvasComponent::class) { - attrs { - this.obj = object3D - this.options = Canvas3DOptions.invoke(options) - } - } -} \ No newline at end of file +//public class ThreeCanvasComponent : RComponent() { +// +// private var canvas: ThreeCanvas? = null +// +// override fun componentDidMount() { +// props.obj?.let { obj -> +// if (canvas == null) { +// val element = state.element as? HTMLElement ?: error("Canvas element not found") +// val three: ThreePlugin = props.context.plugins.fetch(ThreePlugin) +// canvas = three.output(element, props.options ?: Canvas3DOptions.empty()).apply { +// onClick = props.clickCallback +// } +// props.canvasCallback?.invoke(canvas) +// } +// canvas?.render(obj) +// } +// } +// +// override fun componentDidUpdate(prevProps: ThreeCanvasProps, prevState: ThreeCanvasState, snapshot: Any) { +// if (prevProps.obj != props.obj) { +// componentDidMount() +// } +// if (prevProps.selected != props.selected) { +// canvas?.select(props.selected) +// } +// } +// +// override fun RBuilder.render() { +// div { +// ref { +// state.element = findDOMNode(it) +// } +// } +// } +//} \ No newline at end of file From 7571b58e99eafade5257209b33b37d2b30d78070 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Sat, 31 Oct 2020 10:04:23 +0300 Subject: [PATCH 017/151] Versions cleanup --- build.gradle.kts | 3 +- settings.gradle.kts | 1 + ui/bootstrap/build.gradle.kts | 3 +- .../vision/bootstrap/outputConfig.kt | 5 +- ui/react/build.gradle.kts | 9 +- visionforge-core/build.gradle.kts | 14 +- .../kotlin/hep/dataforge/vision/Colors.kt | 3 +- .../vision/visitor/StatisticsVisitor.kt | 8 +- .../dataforge/vision/visitor/VisionVisitor.kt | 12 +- .../kotlin/hep/dataforge/vision/FXPlugin.kt | 20 +- visionforge-server/build.gradle.kts | 66 +++ visionforge-solid/build.gradle.kts | 1 - wrappers/build.gradle.kts | 23 - wrappers/src/main/kotlin/dat.kt | 102 ----- wrappers/src/main/kotlin/eventemitter2.kt | 65 --- wrappers/src/main/kotlin/inspire-tree-dom.kt | 38 -- wrappers/src/main/kotlin/inspire-tree.kt | 417 ------------------ wrappers/src/main/kotlin/jsoneditor.kt | 185 -------- 18 files changed, 102 insertions(+), 873 deletions(-) create mode 100644 visionforge-server/build.gradle.kts delete mode 100644 wrappers/build.gradle.kts delete mode 100644 wrappers/src/main/kotlin/dat.kt delete mode 100644 wrappers/src/main/kotlin/eventemitter2.kt delete mode 100644 wrappers/src/main/kotlin/inspire-tree-dom.kt delete mode 100644 wrappers/src/main/kotlin/inspire-tree.kt delete mode 100644 wrappers/src/main/kotlin/jsoneditor.kt diff --git a/build.gradle.kts b/build.gradle.kts index bc20d61f..25d9f4b9 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -6,6 +6,7 @@ plugins { val dataforgeVersion by extra("0.2.0-dev-4") val ktorVersion by extra("1.4.1") +val kotlinWrappersVersion by extra("pre.129-kotlin-1.4.10") allprojects { repositories { @@ -15,7 +16,7 @@ allprojects { } group = "hep.dataforge" - version = "0.2.0-dev-1" + version = "0.2.0-dev-2" } val githubProject by extra("visionforge") diff --git a/settings.gradle.kts b/settings.gradle.kts index 65690060..8ab3e4e4 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -39,6 +39,7 @@ include( ":visionforge-core", ":visionforge-solid", ":visionforge-gdml", + ":visionforge-server", ":demo:spatial-showcase", ":demo:gdml", ":demo:muon-monitor", diff --git a/ui/bootstrap/build.gradle.kts b/ui/bootstrap/build.gradle.kts index 1cdd834d..8d404277 100644 --- a/ui/bootstrap/build.gradle.kts +++ b/ui/bootstrap/build.gradle.kts @@ -4,7 +4,8 @@ plugins { val dataforgeVersion: String by rootProject.extra -dependencies{ +dependencies { api(project(":visionforge-solid")) api(project(":ui:react")) + implementation(npm("file-saver", "2.0.2")) } \ No newline at end of file diff --git a/ui/bootstrap/src/main/kotlin/hep/dataforge/vision/bootstrap/outputConfig.kt b/ui/bootstrap/src/main/kotlin/hep/dataforge/vision/bootstrap/outputConfig.kt index b6326979..9e5e1a4b 100644 --- a/ui/bootstrap/src/main/kotlin/hep/dataforge/vision/bootstrap/outputConfig.kt +++ b/ui/bootstrap/src/main/kotlin/hep/dataforge/vision/bootstrap/outputConfig.kt @@ -17,6 +17,7 @@ import org.w3c.dom.events.Event import org.w3c.files.Blob import org.w3c.files.BlobPropertyBag import react.RBuilder +import react.ReactElement import react.dom.button import react.dom.div import react.dom.input @@ -32,7 +33,7 @@ private fun saveData(event: Event, fileName: String, mimeType: String = "text/pl } @OptIn(DFExperimental::class) -fun RBuilder.canvasControls(canvas: ThreeCanvas) = accordion("controls") { +public fun RBuilder.canvasControls(canvas: ThreeCanvas): ReactElement = accordion("controls") { entry("Settings") { div("row") { div("col-2") { @@ -96,7 +97,7 @@ fun RBuilder.canvasControls(canvas: ThreeCanvas) = accordion("controls") { } -fun Element.displayCanvasControls(canvas: ThreeCanvas, block: TagConsumer.() -> Unit = {}) { +public fun Element.displayCanvasControls(canvas: ThreeCanvas, block: TagConsumer.() -> Unit = {}) { clear() append { accordion("controls") { diff --git a/ui/react/build.gradle.kts b/ui/react/build.gradle.kts index 8d541ffd..9389bd35 100644 --- a/ui/react/build.gradle.kts +++ b/ui/react/build.gradle.kts @@ -3,14 +3,9 @@ plugins { } val reactVersion by extra("17.0.0") +val kotlinWrappersVersion: String by rootProject.extra dependencies{ api(project(":visionforge-core")) - - //api("org.jetbrains:kotlin-react:16.13.1-pre.104-kotlin-1.3.72") - api("org.jetbrains:kotlin-react-dom:$reactVersion-pre.126-kotlin-1.4.10") - - api(npm("react", reactVersion)) - api(npm("react-dom", reactVersion)) - api(npm("react-is", reactVersion)) + api("org.jetbrains:kotlin-react-dom:$reactVersion-$kotlinWrappersVersion") } \ No newline at end of file diff --git a/visionforge-core/build.gradle.kts b/visionforge-core/build.gradle.kts index 2bf0b6e0..6e59b5da 100644 --- a/visionforge-core/build.gradle.kts +++ b/visionforge-core/build.gradle.kts @@ -3,6 +3,8 @@ plugins { } val dataforgeVersion: String by rootProject.extra +val kotlinWrappersVersion: String by rootProject.extra + kotlin { @@ -27,16 +29,8 @@ kotlin { jsMain { dependencies { api("hep.dataforge:dataforge-output-html:$dataforgeVersion") - api("org.jetbrains.kotlinx:kotlinx-html:0.7.2") - - //api("org.jetbrains:kotlin-extensions:1.0.1-pre.105-kotlin-1.3.72") - //api("org.jetbrains:kotlin-css-js:1.0.0-pre.105-kotlin-1.3.72") - api("org.jetbrains:kotlin-styled:5.2.0-pre.126-kotlin-1.4.10") - - api(npm("core-js", "2.6.5")) - api(npm("inline-style-prefixer", "5.1.0")) - api(npm("styled-components", "5.2.0")) - //api(project(":ringui-wrapper")) + api("org.jetbrains:kotlin-styled:5.2.0-$kotlinWrappersVersion") + api("org.jetbrains:kotlin-extensions:1.0.1-$kotlinWrappersVersion") } } } diff --git a/visionforge-core/src/commonMain/kotlin/hep/dataforge/vision/Colors.kt b/visionforge-core/src/commonMain/kotlin/hep/dataforge/vision/Colors.kt index 4918b6c5..1b3d4763 100644 --- a/visionforge-core/src/commonMain/kotlin/hep/dataforge/vision/Colors.kt +++ b/visionforge-core/src/commonMain/kotlin/hep/dataforge/vision/Colors.kt @@ -12,7 +12,8 @@ import kotlin.math.max * Definitions of common colors. Taken from * https://github.com/markaren/three.kt/blob/master/threejs-wrapper/src/main/kotlin/info/laht/threekt/math/ColorConstants.kt */ -object Colors { +@Suppress("NO_EXPLICIT_VISIBILITY_IN_API_MODE_WARNING", "NO_EXPLICIT_RETURN_TYPE_IN_API_MODE_WARNING") +public object Colors { const val aliceblue = 0xF0F8FF const val antiquewhite = 0xFAEBD7 const val aqua = 0x00FFFF diff --git a/visionforge-core/src/commonMain/kotlin/hep/dataforge/vision/visitor/StatisticsVisitor.kt b/visionforge-core/src/commonMain/kotlin/hep/dataforge/vision/visitor/StatisticsVisitor.kt index 89877fe6..e4a027c9 100644 --- a/visionforge-core/src/commonMain/kotlin/hep/dataforge/vision/visitor/StatisticsVisitor.kt +++ b/visionforge-core/src/commonMain/kotlin/hep/dataforge/vision/visitor/StatisticsVisitor.kt @@ -12,7 +12,7 @@ import kotlin.reflect.KClass @OptIn(ExperimentalCoroutinesApi::class) -suspend fun Vision.flowStatistics(statistics: (Name, Vision) -> T): Flow = callbackFlow { +public suspend fun Vision.flowStatistics(statistics: (Name, Vision) -> T): Flow = callbackFlow { val visitor = object : VisionVisitor { override suspend fun visit(name: Name, vision: Vision){ send(statistics(name, vision)) @@ -27,10 +27,10 @@ suspend fun Vision.flowStatistics(statistics: (Name, Vision) -> T): Flow } } -data class DefaultVisionStatistics(val name: Name, val type: KClass) { - val depth get() = name.length +public data class DefaultVisionStatistics(val name: Name, val type: KClass) { + val depth: Int get() = name.length } -suspend fun Vision.flowStatistics(): Flow = flowStatistics { name, vision -> +public suspend fun Vision.flowStatistics(): Flow = flowStatistics { name, vision -> DefaultVisionStatistics(name, vision::class) } \ No newline at end of file diff --git a/visionforge-core/src/commonMain/kotlin/hep/dataforge/vision/visitor/VisionVisitor.kt b/visionforge-core/src/commonMain/kotlin/hep/dataforge/vision/visitor/VisionVisitor.kt index 192e36a0..4b6e480e 100644 --- a/visionforge-core/src/commonMain/kotlin/hep/dataforge/vision/visitor/VisionVisitor.kt +++ b/visionforge-core/src/commonMain/kotlin/hep/dataforge/vision/visitor/VisionVisitor.kt @@ -8,24 +8,24 @@ import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Job import kotlinx.coroutines.launch -interface VisionVisitor { +public interface VisionVisitor { /** * Visit a vision possibly mutating in in the process. Should not rearrange children. * @param name full name of a [Vision] being visited * @param vision the visited [Vision] */ - suspend fun visit(name: Name, vision: Vision) + public suspend fun visit(name: Name, vision: Vision) /** * Rearrange children of given group */ - suspend fun visitChildren(name: Name, group: VisionGroup) { + public suspend fun visitChildren(name: Name, group: VisionGroup) { //Do nothing by default } - fun skip(name: Name, vision: Vision): Boolean = false + public fun skip(name: Name, vision: Vision): Boolean = false - companion object{ + public companion object{ private fun CoroutineScope.visitTreeAsync( visionVisitor: VisionVisitor, name: Name, @@ -46,7 +46,7 @@ interface VisionVisitor { /** * Recursively visit this [Vision] and all children */ - fun visitTree(visionVisitor: VisionVisitor, scope: CoroutineScope, root: Vision): Job = + public fun visitTree(visionVisitor: VisionVisitor, scope: CoroutineScope, root: Vision): Job = scope.visitTreeAsync(visionVisitor, Name.EMPTY, root) diff --git a/visionforge-core/src/jvmMain/kotlin/hep/dataforge/vision/FXPlugin.kt b/visionforge-core/src/jvmMain/kotlin/hep/dataforge/vision/FXPlugin.kt index 91d1f0c1..11176bf6 100644 --- a/visionforge-core/src/jvmMain/kotlin/hep/dataforge/vision/FXPlugin.kt +++ b/visionforge-core/src/jvmMain/kotlin/hep/dataforge/vision/FXPlugin.kt @@ -19,12 +19,12 @@ import kotlin.reflect.KClass /** * Plugin holding JavaFX application instance and its root stage */ -class FXPlugin(meta: Meta = Meta.EMPTY) : AbstractPlugin(meta) { +public class FXPlugin(meta: Meta = Meta.EMPTY) : AbstractPlugin(meta) { override val tag: PluginTag get() = Companion.tag private val stages: ObservableSet = FXCollections.observableSet() - val consoleMode: Boolean by meta.boolean(true) + public val consoleMode: Boolean by meta.boolean(true) init { if (consoleMode) { @@ -65,7 +65,7 @@ class FXPlugin(meta: Meta = Meta.EMPTY) : AbstractPlugin(meta) { /** * Define an application to use in this context */ - fun setApp(app: Application, stage: Stage) { + public fun setApp(app: Application, stage: Stage) { FX.registerApplication(FX.defaultScope, app, stage) } @@ -74,7 +74,7 @@ class FXPlugin(meta: Meta = Meta.EMPTY) : AbstractPlugin(meta) { * * @param cons */ - fun display(action: Stage.() -> Unit) { + public fun display(action: Stage.() -> Unit) { runLater { val stage = Stage() stage.initOwner(FX.primaryStage) @@ -85,14 +85,14 @@ class FXPlugin(meta: Meta = Meta.EMPTY) : AbstractPlugin(meta) { } } - fun display(component: UIComponent, width: Double = 800.0, height: Double = 600.0) { + public fun display(component: UIComponent, width: Double = 800.0, height: Double = 600.0) { display { scene = Scene(component.root, width, height) title = component.title } } - companion object : PluginFactory { + public companion object : PluginFactory { override val type: KClass = FXPlugin::class override val tag: PluginTag = PluginTag("vis.fx", group = PluginTag.DATAFORGE_GROUP) override fun invoke(meta: Meta, context: Context): FXPlugin = @@ -101,19 +101,19 @@ class FXPlugin(meta: Meta = Meta.EMPTY) : AbstractPlugin(meta) { } -val dfIcon: Image = Image(Global::class.java.getResourceAsStream("/img/df.png")) -val dfIconView = ImageView(dfIcon) +public val dfIcon: Image = Image(Global::class.java.getResourceAsStream("/img/df.png")) +public val dfIconView: ImageView = ImageView(dfIcon) /** * An application surrogate without any visible primary stage */ -class ApplicationSurrogate : App() { +public class ApplicationSurrogate : App() { override fun start(stage: Stage) { FX.registerApplication(this, stage) FX.initialized.value = true } } -fun Context.display(width: Double = 800.0, height: Double = 600.0, component: () -> UIComponent) { +public fun Context.display(width: Double = 800.0, height: Double = 600.0, component: () -> UIComponent) { plugins.fetch(FXPlugin).display(component(), width, height) } \ No newline at end of file diff --git a/visionforge-server/build.gradle.kts b/visionforge-server/build.gradle.kts new file mode 100644 index 00000000..0eec3285 --- /dev/null +++ b/visionforge-server/build.gradle.kts @@ -0,0 +1,66 @@ +import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation.Companion.MAIN_COMPILATION_NAME + +plugins { + id("ru.mipt.npm.mpp") + application +} + +val ktorVersion: String by rootProject.extra + +kscience { + application() +} + +kotlin { + afterEvaluate { + val jsBrowserDistribution by tasks.getting + + jvm { + withJava() + compilations[MAIN_COMPILATION_NAME]?.apply { + tasks.getByName(processResourcesTaskName) { + dependsOn(jsBrowserDistribution) + afterEvaluate { + from(jsBrowserDistribution) + } + } + } + + } + } + + sourceSets { + commonMain { + dependencies { + implementation(project(":visionforge-solid")) + } + } + jvmMain { + dependencies { + implementation("io.ktor:ktor-server-cio:$ktorVersion") + implementation("io.ktor:ktor-serialization:$ktorVersion") + } + } + jsMain { + dependencies { + implementation("io.ktor:ktor-client-js:$ktorVersion") + implementation("io.ktor:ktor-client-serialization-js:$ktorVersion") + } + } + } +} + +application { + mainClass.set("ru.mipt.npm.muon.monitor.server.MMServerKt") +} + +//distributions { +// main { +// contents { +// from("$buildDir/libs") { +// rename("${rootProject.name}-jvm", rootProject.name) +// into("lib") +// } +// } +// } +//} \ No newline at end of file diff --git a/visionforge-solid/build.gradle.kts b/visionforge-solid/build.gradle.kts index aab7e547..3f7ac5dc 100644 --- a/visionforge-solid/build.gradle.kts +++ b/visionforge-solid/build.gradle.kts @@ -31,7 +31,6 @@ kotlin { dependencies { implementation(npm("three", "0.114.0")) implementation(npm("three-csg-ts", "1.0.1")) - api(npm("file-saver", "2.0.2")) } } } diff --git a/wrappers/build.gradle.kts b/wrappers/build.gradle.kts deleted file mode 100644 index 6baa876c..00000000 --- a/wrappers/build.gradle.kts +++ /dev/null @@ -1,23 +0,0 @@ -plugins { - id("scientifik.js") - //id("kotlin-dce-js") -} - -dependencies { - api(project(":visionforge-common")) - - testCompile(kotlin("test-js")) -} - -kotlin{ - sourceSets["main"].apply{ - dependencies{ - api(npm("style-loader")) -// api(npm("inspire-tree","6.0.1")) -// api(npm("inspire-tree-dom","4.0.6")) - api(npm("jsoneditor")) - api(npm("dat.gui")) - //api("org.jetbrains:kotlin-extensions:1.0.1-pre.83-kotlin-1.3.50") - } - } -} diff --git a/wrappers/src/main/kotlin/dat.kt b/wrappers/src/main/kotlin/dat.kt deleted file mode 100644 index 7c56c20a..00000000 --- a/wrappers/src/main/kotlin/dat.kt +++ /dev/null @@ -1,102 +0,0 @@ -@file:Suppress( - "INTERFACE_WITH_SUPERCLASS", - "OVERRIDING_FINAL_MEMBER", - "RETURN_TYPE_MISMATCH_ON_OVERRIDE", - "CONFLICTING_OVERLOADS", - "EXTERNAL_DELEGATION" -) -@file:JsModule("dat.gui") -@file:JsNonModule - -package hep.dataforge.vis.spatial.editor - -import org.w3c.dom.HTMLElement - -external interface GUIParams { - var autoPlace: Boolean? get() = definedExternally; set(value) = definedExternally - var closed: Boolean? get() = definedExternally; set(value) = definedExternally - var closeOnTop: Boolean? get() = definedExternally; set(value) = definedExternally - var hideable: Boolean? get() = definedExternally; set(value) = definedExternally - var load: Any? get() = definedExternally; set(value) = definedExternally - var name: String? get() = definedExternally; set(value) = definedExternally - var preset: String? get() = definedExternally; set(value) = definedExternally - var width: Number? get() = definedExternally; set(value) = definedExternally -} - -external open class GUI(option: GUIParams? = definedExternally /* null */) { - open var __controllers: Array - open var __folders: Array - open var domElement: HTMLElement - open fun add( - target: Any, - propName: String, - min: Number? = definedExternally /* null */, - max: Number? = definedExternally /* null */, - step: Number? = definedExternally /* null */ - ): GUIController - - open fun add(target: Any, propName: String, status: Boolean): GUIController - open fun add(target: Any, propName: String, items: Array): GUIController - open fun add(target: Any, propName: String, items: Array): GUIController - open fun add(target: Any, propName: String, items: Any): GUIController - open fun addColor(target: Any, propName: String): GUIController - open fun remove(controller: GUIController) - open fun destroy() - open fun addFolder(propName: String): GUI - open fun removeFolder(subFolder: GUI) - open fun open() - open fun close() - open fun hide() - open fun show() - open fun remember(target: Any, vararg additionalTargets: Any) - open fun getRoot(): GUI - open fun getSaveObject(): Any - open fun save() - open fun saveAs(presetName: String) - open fun revert(gui: GUI) - open fun listen(controller: GUIController) - open fun updateDisplay() - open var parent: GUI - open var scrollable: Boolean - open var autoPlace: Boolean - open var preset: String - open var width: Number - open var name: String - open var closed: Boolean - open var load: Any - open var useLocalStorage: Boolean - - companion object { - var CLASS_AUTO_PLACE: String - var CLASS_AUTO_PLACE_CONTAINER: String - var CLASS_MAIN: String - var CLASS_CONTROLLER_ROW: String - var CLASS_TOO_TALL: String - var CLASS_CLOSED: String - var CLASS_CLOSE_BUTTON: String - var CLASS_CLOSE_TOP: String - var CLASS_CLOSE_BOTTOM: String - var CLASS_DRAG: String - var DEFAULT_WIDTH: Number - var TEXT_CLOSED: String - var TEXT_OPEN: String - } -} - -external open class GUIController { - open fun destroy() - open var onChange: (value: Any? /* = null */) -> GUIController - open var onFinishChange: (value: Any? /* = null */) -> GUIController - open fun setValue(value: Any): GUIController - open fun getValue(): Any - open fun updateDisplay(): GUIController - open fun isModified(): Boolean - open fun min(n: Number): GUIController - open fun max(n: Number): GUIController - open fun step(n: Number): GUIController - open fun fire(): GUIController - open fun options(option: Any): GUIController - open fun name(s: String): GUIController - open fun listen(): GUIController - open fun remove(): GUIController -} \ No newline at end of file diff --git a/wrappers/src/main/kotlin/eventemitter2.kt b/wrappers/src/main/kotlin/eventemitter2.kt deleted file mode 100644 index 36b925f2..00000000 --- a/wrappers/src/main/kotlin/eventemitter2.kt +++ /dev/null @@ -1,65 +0,0 @@ -@file:Suppress( - "INTERFACE_WITH_SUPERCLASS", - "OVERRIDING_FINAL_MEMBER", - "RETURN_TYPE_MISMATCH_ON_OVERRIDE", - "CONFLICTING_OVERLOADS", - "EXTERNAL_DELEGATION" -) -@file:JsModule("eventemitter2") -@file: JsNonModule - -package hep.dataforge.vis.spatial.editor - -import kotlin.js.Promise - -//typealias eventNS = Array - -external interface ConstructorOptions { - var wildcard: Boolean? get() = definedExternally; set(value) = definedExternally - var delimiter: String? get() = definedExternally; set(value) = definedExternally - var newListener: Boolean? get() = definedExternally; set(value) = definedExternally - var maxListeners: Number? get() = definedExternally; set(value) = definedExternally - var verboseMemoryLeak: Boolean? get() = definedExternally; set(value) = definedExternally -} - -external interface EventAndListener { - @nativeInvoke - operator fun invoke(event: String, vararg values: Any) - - @nativeInvoke - operator fun invoke(event: Array, vararg values: Any) -} - -external open class EventEmitter2(options: ConstructorOptions? = definedExternally /* null */) { - open fun emit(event: String, vararg values: Any): Boolean - open fun emit(event: Array, vararg values: Any): Boolean - open fun emitAsync(event: String, vararg values: Any): Promise> - open fun emitAsync(event: Array, vararg values: Any): Promise> - open fun addListener(event: String, listener: Function<*>): EventEmitter2 /* this */ - open fun on(event: String, listener: Function<*>): EventEmitter2 /* this */ - open fun on(event: Array, listener: Function<*>): EventEmitter2 /* this */ - open fun prependListener(event: String, listener: Function<*>): EventEmitter2 /* this */ - open fun prependListener(event: Array, listener: Function<*>): EventEmitter2 /* this */ - open fun once(event: String, listener: Function<*>): EventEmitter2 /* this */ - open fun once(event: Array, listener: Function<*>): EventEmitter2 /* this */ - open fun prependOnceListener(event: String, listener: Function<*>): EventEmitter2 /* this */ - open fun prependOnceListener(event: Array, listener: Function<*>): EventEmitter2 /* this */ - open fun many(event: String, timesToListen: Number, listener: Function<*>): EventEmitter2 /* this */ - open fun many(event: Array, timesToListen: Number, listener: Function<*>): EventEmitter2 /* this */ - open fun prependMany(event: String, timesToListen: Number, listener: Function<*>): EventEmitter2 /* this */ - open fun prependMany(event: Array, timesToListen: Number, listener: Function<*>): EventEmitter2 /* this */ - open fun onAny(listener: EventAndListener): EventEmitter2 /* this */ - open fun prependAny(listener: EventAndListener): EventEmitter2 /* this */ - open fun offAny(listener: Function<*>): EventEmitter2 /* this */ - open fun removeListener(event: String, listener: Function<*>): EventEmitter2 /* this */ - open fun removeListener(event: Array, listener: Function<*>): EventEmitter2 /* this */ - open fun off(event: String, listener: Function<*>): EventEmitter2 /* this */ - open fun removeAllListeners(event: String? = definedExternally /* null */): EventEmitter2 /* this */ - open fun removeAllListeners(event: Array? = definedExternally /* null */): EventEmitter2 /* this */ - open fun setMaxListeners(n: Number) - open fun eventNames(): Array - open fun listeners(event: String): Array> - open fun listeners(event: Array): Array> - open fun listenersAny(): Array> - open fun removeAllListeners(): EventEmitter2 /* this */ -} \ No newline at end of file diff --git a/wrappers/src/main/kotlin/inspire-tree-dom.kt b/wrappers/src/main/kotlin/inspire-tree-dom.kt deleted file mode 100644 index f3e00d08..00000000 --- a/wrappers/src/main/kotlin/inspire-tree-dom.kt +++ /dev/null @@ -1,38 +0,0 @@ -@file:Suppress( - "INTERFACE_WITH_SUPERCLASS", - "OVERRIDING_FINAL_MEMBER", - "RETURN_TYPE_MISMATCH_ON_OVERRIDE", - "CONFLICTING_OVERLOADS", - "EXTERNAL_DELEGATION" -) - -package hep.dataforge.vis.spatial.editor - -import org.w3c.dom.HTMLElement - -external interface DropTargetValidator { - @nativeInvoke - operator fun invoke(dragNode: TreeNode, targetNode: TreeNode): Boolean -} - -external interface DragAndDrop { - var enabled: Boolean? get() = definedExternally; set(value) = definedExternally - var validateOn: String? get() = definedExternally; set(value) = definedExternally - var validate: DropTargetValidator -} - -external interface DomConfig { - var autoLoadMore: Boolean? get() = definedExternally; set(value) = definedExternally - var deferredRendering: Boolean? get() = definedExternally; set(value) = definedExternally - var dragAndDrop: DragAndDrop? get() = definedExternally; set(value) = definedExternally - var nodeHeight: Number? get() = definedExternally; set(value) = definedExternally - var showCheckboxes: Boolean? get() = definedExternally; set(value) = definedExternally - var dragTargets: Array? get() = definedExternally; set(value) = definedExternally - var tabindex: Number? get() = definedExternally; set(value) = definedExternally - var target: HTMLElement -} - - -@JsModule("inspire-tree-dom") -@JsNonModule -open external class InspireTreeDOM(tree: Any, opts: DomConfig) \ No newline at end of file diff --git a/wrappers/src/main/kotlin/inspire-tree.kt b/wrappers/src/main/kotlin/inspire-tree.kt deleted file mode 100644 index 74887be7..00000000 --- a/wrappers/src/main/kotlin/inspire-tree.kt +++ /dev/null @@ -1,417 +0,0 @@ -@file:Suppress( - "INTERFACE_WITH_SUPERCLASS", - "OVERRIDING_FINAL_MEMBER", - "RETURN_TYPE_MISMATCH_ON_OVERRIDE", - "CONFLICTING_OVERLOADS", - "EXTERNAL_DELEGATION", - "unused" -) - -package hep.dataforge.vis.spatial.editor - -import kotlin.js.Promise -import kotlin.js.RegExp - -external interface NodeIteratee { - @nativeInvoke - operator fun invoke(node: TreeNode): Any -} - -external interface MatchProcessor { - @nativeInvoke - operator fun invoke(matches: TreeNodes): Any -} - -external interface SearchMatcher { - @nativeInvoke - operator fun invoke(query: String, resolve: Any, reject: Any): Any -} - -external interface `T$0` { - var add: Boolean? get() = definedExternally; set(value) = definedExternally - var edit: Boolean? get() = definedExternally; set(value) = definedExternally - var remove: Boolean? get() = definedExternally; set(value) = definedExternally -} - -external interface `T$1` { - var resetStateOnRestore: Boolean? get() = definedExternally; set(value) = definedExternally -} - -external interface `T$2` { - var limit: Number? get() = definedExternally; set(value) = definedExternally -} - -external interface `T$3` { - var matcher: SearchMatcher - var matchProcess: MatchProcessor -} - -external interface Selection { - var allow: NodeIteratee? get() = definedExternally; set(value) = definedExternally - var autoDeselect: Boolean? get() = definedExternally; set(value) = definedExternally - var autoSelectChildren: Boolean? get() = definedExternally; set(value) = definedExternally - var disableDirectDeselection: Boolean? get() = definedExternally; set(value) = definedExternally - var mode: String? get() = definedExternally; set(value) = definedExternally - var multiple: Boolean? get() = definedExternally; set(value) = definedExternally - var require: Boolean? get() = definedExternally; set(value) = definedExternally -} - -external interface Config { - var allowLoadEvents: Array? get() = definedExternally; set(value) = definedExternally -// var checkbox: dynamic get() = definedExternally; set(value) = definedExternally - var contextMenu: Boolean? get() = definedExternally; set(value) = definedExternally - val data: ((node: TreeNode, resolve: (nodes: Array) -> Any, reject: (err: Error) -> Any) -> dynamic)? get() = definedExternally - var deferredLoading: Boolean? get() = definedExternally; set(value) = definedExternally - var editable: Boolean? get() = definedExternally; set(value) = definedExternally - var editing: `T$0`? get() = definedExternally; set(value) = definedExternally - var nodes: `T$1`? get() = definedExternally; set(value) = definedExternally - var pagination: `T$2`? get() = definedExternally; set(value) = definedExternally - var renderer: Any? get() = definedExternally; set(value) = definedExternally - var search: `T$3`? get() = definedExternally; set(value) = definedExternally - var selection: Selection? get() = definedExternally; set(value) = definedExternally - var sort: String? get() = definedExternally; set(value) = definedExternally - var multiselect: Boolean? get() = definedExternally; set(value) = definedExternally -} - -external interface State { - var checked: Boolean? get() = definedExternally; set(value) = definedExternally - var collapsed: Boolean? get() = definedExternally; set(value) = definedExternally - var draggable: Boolean? get() = definedExternally; set(value) = definedExternally - //var `drop-target`: Boolean? get() = definedExternally; set(value) = definedExternally - var editable: Boolean? get() = definedExternally; set(value) = definedExternally - var focused: Boolean? get() = definedExternally; set(value) = definedExternally - var hidden: Boolean? get() = definedExternally; set(value) = definedExternally - var indeterminate: Boolean? get() = definedExternally; set(value) = definedExternally - var loading: Boolean? get() = definedExternally; set(value) = definedExternally - var matched: Boolean? get() = definedExternally; set(value) = definedExternally - var removed: Boolean? get() = definedExternally; set(value) = definedExternally - var rendered: Boolean? get() = definedExternally; set(value) = definedExternally - var selectable: Boolean? get() = definedExternally; set(value) = definedExternally - var selected: Boolean? get() = definedExternally; set(value) = definedExternally -} - -external interface InspireTag { - var attributes: Any? get() = definedExternally; set(value) = definedExternally -} - -external interface ITree { - var a: InspireTag? get() = definedExternally; set(value) = definedExternally - var icon: String? get() = definedExternally; set(value) = definedExternally - var li: InspireTag? get() = definedExternally; set(value) = definedExternally - var state: State? get() = definedExternally; set(value) = definedExternally -} - -external interface NodeConfig { - var children: dynamic /* Array | true */ - var id: String? get() = definedExternally; set(value) = definedExternally - var text: String - @JsName("itree") - var itree: ITree? get() = definedExternally; set(value) = definedExternally -} - -external interface Pagination { - var limit: Number - var total: Number -} - -@JsModule("inspire-tree") -@JsNonModule -open external class InspireTree(opts: Config) : EventEmitter2 { - constructor(tree: InspireTree) - constructor(tree: InspireTree, array: Array) - constructor(tree: InspireTree, array: TreeNodes) - - open fun addNode(node: NodeConfig): TreeNode - open fun addNodes(node: Array): TreeNodes - open fun available(): TreeNodes - open fun blur(): TreeNodes - open fun blurDeep(): TreeNodes - open fun boundingNodes(): Array - open fun canAutoDeselect(): Boolean - open fun checked(): TreeNodes - open fun clean(): TreeNodes - open fun clearSearch(): InspireTree - open fun clone(): TreeNodes - open fun collapse(): TreeNodes - open fun collapsed(full: Boolean? = definedExternally /* null */): TreeNodes - open fun collapseDeep(): TreeNodes - open fun context(): TreeNode - open fun copy( - dest: InspireTree, - hierarchy: Boolean? = definedExternally /* null */, - includeState: Boolean? = definedExternally /* null */ - ): TreeNodes - - open fun createNode(obj: Any): TreeNode - open fun deepest(): TreeNodes - open fun deselect(): TreeNodes - open fun deselectDeep(): TreeNodes - open fun disableDeselection(): InspireTree - open fun each(iteratee: NodeIteratee): TreeNodes - open fun editable(full: Boolean? = definedExternally /* null */): TreeNodes - open fun editing(full: Boolean? = definedExternally /* null */): TreeNodes - open fun enableDeselection(): InspireTree - open fun expand(): Promise - open fun expandDeep(): TreeNodes - open fun expanded(full: Boolean? = definedExternally /* null */): TreeNodes - open fun expandParents(): TreeNodes - open fun extract(predicate: String): TreeNodes - open fun extract(predicate: NodeIteratee): TreeNodes - open fun filterBy(predicate: String): TreeNodes - open fun filterBy(predicate: NodeIteratee): TreeNodes - open fun find( - predicate: (node: TreeNode, index: Number? /* = null */, obj: Array? /* = null */) -> Boolean, - thisArg: Any? = definedExternally /* null */ - ): TreeNode - - open fun first(predicate: (node: TreeNode) -> Boolean): TreeNode - open fun flatten(predicate: String): TreeNodes - open fun flatten(predicate: NodeIteratee): TreeNodes - open fun focused(full: Boolean? = definedExternally /* null */): TreeNodes - open fun get(index: Number): TreeNode - open fun hidden(full: Boolean? = definedExternally /* null */): TreeNodes - open fun hide(): TreeNodes - open fun hideDeep(): TreeNodes - open var id: dynamic /* String | Number */ - open var config: Config - open var preventDeselection: Boolean - open fun indeterminate(full: Boolean? = definedExternally /* null */): TreeNodes - open fun insertAt(index: Number, `object`: Any): TreeNode - open fun invoke(methods: String): TreeNodes - open fun invoke(methods: Array): TreeNodes - open fun invokeDeep(methods: String): TreeNodes - open fun invokeDeep(methods: Array): TreeNodes - open fun isEventMuted(eventName: String): Boolean - open fun last(predicate: (node: TreeNode) -> Boolean): TreeNode - open fun lastSelectedNode(): TreeNode - open fun load(loader: Promise): Promise - open fun loading(full: Boolean? = definedExternally /* null */): TreeNodes - open fun matched(full: Boolean? = definedExternally /* null */): TreeNodes - open fun move(index: Number, newIndex: Number, target: TreeNodes): TreeNode - open fun mute(events: Array): InspireTree - open fun muted(): Boolean - open fun node(id: String): TreeNode - open fun node(id: Number): TreeNode - open fun nodes(ids: Array? = definedExternally /* null */): TreeNodes - open fun nodes(ids: Array? = definedExternally /* null */): TreeNodes - open fun pagination(): Pagination - open fun recurseDown(iteratee: NodeIteratee): TreeNodes - open fun reload(): Promise - open fun removeAll(): InspireTree - open fun removed(full: Boolean? = definedExternally /* null */): TreeNodes - open fun restore(): TreeNodes - open fun restoreDeep(): TreeNodes - open fun search(query: String): Promise - open fun search(query: RegExp): Promise - open fun search(query: NodeIteratee): Promise - open fun select(): TreeNodes - open fun selectable(full: Boolean? = definedExternally /* null */): TreeNodes - open fun selectBetween(start: TreeNode, end: TreeNode): InspireTree - open fun selectDeep(): TreeNodes - open fun selected(full: Boolean? = definedExternally /* null */): TreeNodes - open fun selectFirstAvailableNode(): TreeNode - open fun show(): TreeNodes - open fun showDeep(): TreeNodes - open fun softRemove(): TreeNodes - open fun sortBy(sorter: String): TreeNodes - open fun sortBy(sorter: NodeIteratee): TreeNodes - open fun state(key: String, `val`: Boolean): TreeNodes - open fun stateDeep(key: String, `val`: Boolean): TreeNodes - open fun swap(node1: TreeNode, node2: TreeNode): TreeNodes - open fun toArray(): Array - open fun toArray(): Array - open fun tree(): InspireTree - open fun unmute(events: Array): InspireTree - open fun visible(full: Boolean? = definedExternally /* null */): TreeNodes - open fun nodes(): TreeNodes - - companion object { - fun isTreeNode(`object`: Any): Boolean - fun isTreeNodes(`object`: Any): Boolean - } -} - -open external class TreeNodes(tree: InspireTree) { - constructor(tree: InspireTree, array: Array) - constructor(tree: InspireTree, array: TreeNodes) - - open fun addNode(node: NodeConfig): TreeNode - open fun available(): TreeNodes - open fun blur(): TreeNodes - open fun blurDeep(): TreeNodes - open fun checked(): TreeNodes - open fun clean(): TreeNodes - open fun clone(): TreeNodes - open fun collapse(): TreeNodes - open fun collapsed(full: Boolean? = definedExternally /* null */): TreeNodes - open fun collapseDeep(): TreeNodes - open fun context(): TreeNode - open fun copy( - dest: InspireTree, - hierarchy: Boolean? = definedExternally /* null */, - includeState: Boolean? = definedExternally /* null */ - ): TreeNodes - - open fun deepest(): TreeNodes - open fun deselect(): TreeNodes - open fun deselectDeep(): TreeNodes - open fun each(iteratee: NodeIteratee): TreeNodes - open fun editable(full: Boolean? = definedExternally /* null */): TreeNodes - open fun editing(full: Boolean? = definedExternally /* null */): TreeNodes - open fun expand(): TreeNodes - open fun expandDeep(): Promise - open fun expanded(full: Boolean? = definedExternally /* null */): TreeNodes - open fun expandParents(): TreeNodes - open fun extract(predicate: String): TreeNodes - open fun extract(predicate: NodeIteratee): TreeNodes - open fun filterBy(predicate: String): TreeNodes - open fun filterBy(predicate: NodeIteratee): TreeNodes - open fun find( - predicate: (node: TreeNode, index: Number? /* = null */, obj: Array? /* = null */) -> Boolean, - thisArg: Any? = definedExternally /* null */ - ): TreeNode - - open fun flatten(predicate: String): TreeNodes - open fun flatten(predicate: NodeIteratee): TreeNodes - open fun focused(full: Boolean? = definedExternally /* null */): TreeNodes - operator fun get(index: Number): TreeNode - open fun hidden(full: Boolean? = definedExternally /* null */): TreeNodes - open fun hide(): TreeNodes - open fun hideDeep(): TreeNodes - open fun indeterminate(full: Boolean? = definedExternally /* null */): TreeNodes - open fun insertAt(index: Number, `object`: Any): TreeNode - open fun invoke(methods: String): TreeNodes - open fun invoke(methods: Array): TreeNodes - open fun invokeDeep(methods: String): TreeNodes - open fun invokeDeep(methods: Array): TreeNodes - open fun loading(full: Boolean? = definedExternally /* null */): TreeNodes - open fun matched(full: Boolean? = definedExternally /* null */): TreeNodes - open fun move(index: Number, newIndex: Number, target: TreeNodes): TreeNode - open fun node(id: String): TreeNode - open fun node(id: Number): TreeNode - open fun nodes(ids: Array? = definedExternally /* null */): TreeNodes - open fun nodes(ids: Array? = definedExternally /* null */): TreeNodes - open fun pagination(): Pagination - open fun recurseDown(iteratee: NodeIteratee): TreeNodes - open fun removed(full: Boolean? = definedExternally /* null */): TreeNodes - open fun restore(): TreeNodes - open fun restoreDeep(): TreeNodes - open fun select(): TreeNodes - open fun selectable(full: Boolean? = definedExternally /* null */): TreeNodes - open fun selectBetween(start: TreeNode, end: TreeNode): InspireTree - open fun selectDeep(): TreeNodes - open fun selected(full: Boolean? = definedExternally /* null */): TreeNodes - open fun show(): TreeNodes - open fun showDeep(): TreeNodes - open fun softRemove(): TreeNodes - open fun sortBy(sorter: String): TreeNodes - open fun sortBy(sorter: NodeIteratee): TreeNodes - open fun state(key: String, `val`: Boolean): TreeNodes - open fun stateDeep(key: String, `val`: Boolean): TreeNodes - open fun swap(node1: TreeNode, node2: TreeNode): TreeNodes - open fun toArray(): Array - open fun tree(): InspireTree - open fun visible(full: Boolean? = definedExternally /* null */): TreeNodes - open fun nodes(): TreeNodes -} - -open external class TreeNode(tree: InspireTree) { - constructor(tree: InspireTree, source: Any, excludeKeys: Array) - constructor(tree: InspireTree, source: TreeNode, excludeKeys: Array) - constructor(tree: InspireTree, source: Any) - constructor(tree: InspireTree, source: TreeNode) - - open fun addChild(node: NodeConfig): TreeNode - open fun addChildren(nodes: Array): TreeNodes - open fun assign(vararg sources: Any?): TreeNode - open fun available(): Boolean - open fun blur(): TreeNode - open fun check(shallow: Boolean? = definedExternally /* null */): TreeNode - open fun checked(): Boolean - open fun clean(): TreeNode - open fun clone(excludeKeys: Array? = definedExternally /* null */): TreeNode - open fun collapse(): TreeNode - open fun collapsed(): Boolean - open var text: String - open var id: String - open var itree: Any - open fun context(): TreeNodes - open fun copy( - dest: InspireTree, - hierarchy: Boolean? = definedExternally /* null */, - includeState: Boolean? = definedExternally /* null */ - ): TreeNode - - open fun copyHierarchy( - excludeNode: Boolean? = definedExternally /* null */, - includeState: Boolean? = definedExternally /* null */ - ): TreeNode - - open fun deselect(shallow: Boolean? = definedExternally /* null */): TreeNode - open fun editable(): Boolean - open fun editing(): Boolean - open fun expand(): Promise - open fun expanded(): Boolean - open fun expandParents(): TreeNode - open fun focus(): TreeNode - open fun focused(): Boolean - open fun getChildren(): TreeNodes - open fun getParent(): TreeNode - open fun getParents(): TreeNodes - open fun getTextualHierarchy(): Array - open fun hasAncestor(): Boolean - open fun hasChildren(): Boolean - open fun hasOrWillHaveChildren(): Boolean - open fun hasParent(): Boolean - open fun hasVisibleChildren(): Boolean - open fun hidden(): Boolean - open fun hide(): TreeNode - open fun indeterminate(): Boolean - open fun indexPath(): String - open fun isFirstRenderable(): Boolean - open fun isLastRenderable(): Boolean - open fun lastDeepestVisibleChild(): TreeNode - open fun loadChildren(): Promise - open fun loading(): Boolean - open fun markDirty(): TreeNode - open fun matched(): TreeNodes - open fun nextVisibleAncestralSiblingNode(): TreeNode - open fun nextVisibleChildNode(): TreeNode - open fun nextVisibleNode(): TreeNode - open fun nextVisibleSiblingNode(): TreeNode - open fun pagination(): Pagination - open fun previousVisibleNode(): TreeNode - open fun previousVisibleSiblingNode(): TreeNode - open fun recurseDown(iteratee: NodeIteratee): TreeNode - open fun recurseUp(iteratee: NodeIteratee): TreeNode - open fun refreshIndeterminateState(): TreeNode - open fun reload(): Promise - open fun remove(includeState: Boolean? = definedExternally /* null */): Any - open fun removed(): Boolean - open fun renderable(): Boolean - open fun rendered(): Boolean - open fun restore(): TreeNode - open fun select(shallow: Boolean? = definedExternally /* null */): TreeNode - open fun selectable(): Boolean - open fun selected(): Boolean - open fun set(key: Number, `val`: Any): TreeNode - open fun set(key: String, `val`: Any): TreeNode - open fun show(): TreeNode - open fun softRemove(): TreeNode - open fun state(key: Any?, `val`: Boolean? = definedExternally /* null */): dynamic /* Boolean | Any? */ - open fun state(key: String, `val`: Boolean? = definedExternally /* null */): dynamic /* Boolean | Any? */ - open fun states(keys: Array, `val`: Boolean): Boolean - open fun toggleCheck(): TreeNode - open fun toggleCollapse(): TreeNode - open fun toggleEditing(): TreeNode - open fun toggleSelect(): TreeNode - open fun toObject( - excludeChildren: Boolean? = definedExternally /* null */, - includeState: Boolean? = definedExternally /* null */ - ): Any - - override fun toString(): String - open fun tree(): InspireTree - open fun uncheck(shallow: Boolean? = definedExternally /* null */): TreeNode - open fun visible(): Boolean -} \ No newline at end of file diff --git a/wrappers/src/main/kotlin/jsoneditor.kt b/wrappers/src/main/kotlin/jsoneditor.kt deleted file mode 100644 index a83f4b87..00000000 --- a/wrappers/src/main/kotlin/jsoneditor.kt +++ /dev/null @@ -1,185 +0,0 @@ -@file:Suppress( - "INTERFACE_WITH_SUPERCLASS", - "OVERRIDING_FINAL_MEMBER", - "RETURN_TYPE_MISMATCH_ON_OVERRIDE", - "CONFLICTING_OVERLOADS", - "EXTERNAL_DELEGATION" -) - -package hep.dataforge.vis.spatial.editor - -import org.w3c.dom.HTMLElement - -external interface Node { - var field: String - var value: String? get() = definedExternally; set(value) = definedExternally - var path: dynamic -} - -external interface NodeName { - var path: Array - var type: dynamic /* 'object' | 'array' */ - var size: Number -} - -external interface ValidationError { - var path: dynamic - var message: String -} - -external interface Template { - var text: String - var title: String - var className: String? get() = definedExternally; set(value) = definedExternally - var field: String - var value: Any -} - -external interface `T$6` { - var startFrom: Number - var options: Array -} - -external interface AutoCompleteOptions { - var confirmKeys: Array? get() = definedExternally; set(value) = definedExternally - var caseSensitive: Boolean? get() = definedExternally; set(value) = definedExternally -// var getOptions: AutoCompleteOptionsGetter? get() = definedExternally; set(value) = definedExternally -} - -external interface SelectionPosition { - var row: Number - var column: Number -} - -external interface SerializableNode { - var value: Any - var path: dynamic -} - -external interface Color { - var rgba: Array - var hsla: Array - var rgbString: String - var rgbaString: String - var hslString: String - var hslaString: String - var hex: String -} - -//external interface `T$0` { -// var field: Boolean -// var value: Boolean -//} -// -//external interface `T$1` { -// @nativeGetter -// operator fun get(key: String): String? -// -// @nativeSetter -// operator fun set(key: String, value: String) -//} - -//external interface Languages { -// @nativeGetter -// operator fun get(lang: String): `T$1`? -// -// @nativeSetter -// operator fun set(lang: String, value: `T$1`) -//} - -external interface JSONEditorOptions { -// var ace: AceAjax.Ace? get() = definedExternally; set(value) = definedExternally -// var ajv: Ajv? get() = definedExternally; set(value) = definedExternally - var onChange: (() -> Unit)? get() = definedExternally; set(value) = definedExternally - var onChangeJSON: ((json: Any) -> Unit)? get() = definedExternally; set(value) = definedExternally - var onChangeText: ((jsonString: String) -> Unit)? get() = definedExternally; set(value) = definedExternally - var onEditable: ((node: Node) -> dynamic)? get() = definedExternally; set(value) = definedExternally - var onError: ((error: Error) -> Unit)? get() = definedExternally; set(value) = definedExternally - var onModeChange: ((newMode: dynamic /* 'tree' | 'view' | 'form' | 'code' | 'text' */, oldMode: dynamic /* 'tree' | 'view' | 'form' | 'code' | 'text' */) -> Unit)? get() = definedExternally; set(value) = definedExternally - var onNodeName: ((nodeName: NodeName) -> String?)? get() = definedExternally; set(value) = definedExternally - var onValidate: ((json: Any) -> dynamic)? get() = definedExternally; set(value) = definedExternally - var escapeUnicode: Boolean? get() = definedExternally; set(value) = definedExternally - var sortObjectKeys: Boolean? get() = definedExternally; set(value) = definedExternally - var history: Boolean? get() = definedExternally; set(value) = definedExternally - var mode: dynamic /* 'tree' | 'view' | 'form' | 'code' | 'text' */ - var modes: Array? get() = definedExternally; set(value) = definedExternally - var name: String? get() = definedExternally; set(value) = definedExternally - var schema: Any? get() = definedExternally; set(value) = definedExternally - var schemaRefs: Any? get() = definedExternally; set(value) = definedExternally - var search: Boolean? get() = definedExternally; set(value) = definedExternally - var indentation: Number? get() = definedExternally; set(value) = definedExternally - var theme: String? get() = definedExternally; set(value) = definedExternally - var templates: Array