Demo structure change and fx update

This commit is contained in:
Alexander Nozik 2019-12-24 14:14:10 +03:00
parent a564e078e5
commit 8d39a3efa5
43 changed files with 514 additions and 81 deletions
dataforge-vis-common
dataforge-vis-spatial-gdml/src
commonMain/kotlin/hep/dataforge/vis/spatial/gdml
jsMain/web/css
jvmMain/kotlin/hep/dataforge/vis/spatial/gdml
dataforge-vis-spatial
build.gradle.kts
src
jsMain/kotlin/hep/dataforge/vis/spatial/three
jvmMain/kotlin/hep/dataforge/vis/spatial/fx
demo
build.gradle.kts
gdml
build.gradle.kts
src
jsMain
kotlin/hep/dataforge/vis/spatial/gdml/demo
web
jvmMain/kotlin/hep/dataforge/vis/spatial/gdml/demo
spatial-showcase
build.gradle.kts
src
commonMain/kotlin/hep/dataforge/vis/spatial/demo
jsMain
kotlin/hep/dataforge/vis/spatial/demo
web
jvmMain/kotlin/hep/dataforge/vis/spatial/demo
settings.gradle.kts

@ -29,6 +29,7 @@ kotlin {
dependencies {
api("hep.dataforge:dataforge-output-html:$dataforgeVersion")
api(npm("bootstrap","4.4.1"))
implementation(npm("jsoneditor"))
}
}
}

@ -27,18 +27,21 @@ class StyleSheet() {
return styleMap[key] ?: (owner?.parent as? VisualGroup)?.styleSheet?.get(key)
}
operator fun set(key: String, style: Meta?) {
val oldStyle = styleMap[key]
/**
* Define a style without notifying
*/
fun define(key: String, style: Meta?) {
if (style == null) {
styleMap.remove(key)
} else {
styleMap[key] = style
}
owner?.styleChanged(key, oldStyle, style)
}
infix fun String.put(style: Meta?) {
set(this, style)
operator fun set(key: String, style: Meta?) {
val oldStyle = styleMap[key]
define(key, style)
owner?.styleChanged(key, oldStyle, style)
}
operator fun set(key: String, builder: MetaBuilder.() -> Unit) {

@ -1,6 +1,7 @@
package hep.dataforge.js
external fun require(name: String): dynamic
@JsName("require")
external fun requireJS(name: String): dynamic
inline fun <T : Any> jsObject(builder: T.() -> Unit): T {
val obj: T = js("({})") as T

@ -1,4 +1,4 @@
package hep.dataforge.vis.spatial.editor
package hep.dataforge.vis.js.editor
import kotlinx.html.TagConsumer
import kotlinx.html.js.div

@ -4,7 +4,7 @@ import hep.dataforge.names.NameToken
import hep.dataforge.vis.common.VisualGroup
import hep.dataforge.vis.common.VisualObject
import hep.dataforge.vis.common.isEmpty
import hep.dataforge.vis.spatial.editor.card
import hep.dataforge.vis.js.editor.card
import kotlinx.html.TagConsumer
import kotlinx.html.dom.append
import kotlinx.html.js.*

@ -0,0 +1,185 @@
@file:Suppress(
"INTERFACE_WITH_SUPERCLASS",
"OVERRIDING_FINAL_MEMBER",
"RETURN_TYPE_MISMATCH_ON_OVERRIDE",
"CONFLICTING_OVERLOADS",
"EXTERNAL_DELEGATION"
)
package hep.dataforge.vis.js.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<String>
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<String>
}
external interface AutoCompleteOptions {
var confirmKeys: Array<Number>? 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<Number>
var hsla: Array<Number>
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<dynamic /* 'tree' | 'view' | 'form' | 'code' | 'text' */>? 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<Template>? get() = definedExternally; set(value) = definedExternally
var autocomplete: AutoCompleteOptions? get() = definedExternally; set(value) = definedExternally
var mainMenuBar: Boolean? get() = definedExternally; set(value) = definedExternally
var navigationBar: Boolean? get() = definedExternally; set(value) = definedExternally
var statusBar: Boolean? get() = definedExternally; set(value) = definedExternally
var onTextSelectionChange: ((start: SelectionPosition, end: SelectionPosition, text: String) -> Unit)? get() = definedExternally; set(value) = definedExternally
var onSelectionChange: ((start: SerializableNode, end: SerializableNode) -> Unit)? get() = definedExternally; set(value) = definedExternally
var onEvent: ((node: Node, event: String) -> Unit)? get() = definedExternally; set(value) = definedExternally
var colorPicker: Boolean? get() = definedExternally; set(value) = definedExternally
var onColorPicker: ((parent: HTMLElement, color: String, onChange: (color: Color) -> Unit) -> Unit)? get() = definedExternally; set(value) = definedExternally
var timestampTag: Boolean? get() = definedExternally; set(value) = definedExternally
var language: String? get() = definedExternally; set(value) = definedExternally
//var languages: Languages? get() = definedExternally; set(value) = definedExternally
var modalAnchor: HTMLElement? get() = definedExternally; set(value) = definedExternally
var enableSort: Boolean? get() = definedExternally; set(value) = definedExternally
var enableTransform: Boolean? get() = definedExternally; set(value) = definedExternally
var maxVisibleChilds: Number? get() = definedExternally; set(value) = definedExternally
}
external interface JsonPath {
var path: dynamic
}
external interface EditorSelection {
var start: SerializableNode
var end: SerializableNode
}
external interface TextSelection {
var start: SelectionPosition
var end: SelectionPosition
var text: String
}
@JsModule("jsoneditor")
@JsNonModule
external open class JSONEditor(
container: HTMLElement,
options: JSONEditorOptions? = definedExternally /* null */,
json: dynamic = definedExternally /* null */
) {
open fun collapseAll()
open fun destroy()
open fun expandAll()
open fun focus()
open fun get(): Any
open fun getMode(): dynamic /* 'tree' | 'view' | 'form' | 'code' | 'text' */
open fun getName(): String?
open fun getNodesByRange(start: JsonPath, end: JsonPath): Array<SerializableNode>
open fun getSelection(): EditorSelection
open fun getText(): String
open fun getTextSelection(): TextSelection
open fun refresh()
open fun set(json: Any)
open fun setMode(mode: String /* 'tree' */)
open fun setMode(mode: String /* 'view' */)
open fun setMode(mode: String /* 'form' */)
open fun setMode(mode: String /* 'code' */)
open fun setMode(mode: String /* 'text' */)
open fun setName(name: String? = definedExternally /* null */)
open fun setSchema(schema: Any?, schemaRefs: Any? = definedExternally /* null */)
open fun setSelection(start: JsonPath, end: JsonPath)
open fun setText(jsonString: String)
open fun setTextSelection(start: SelectionPosition, end: SelectionPosition)
open fun update(json: Any)
open fun updateText(jsonString: String)
companion object {
var VALID_OPTIONS: Array<String>
// var ace: AceAjax.Ace
// var Ajv: Ajv
var VanillaPicker: Any
}
}

@ -1,17 +1,12 @@
package hep.dataforge.vis.spatial.editor
package hep.dataforge.vis.js.editor
import hep.dataforge.io.toJson
import hep.dataforge.js.jsObject
import hep.dataforge.meta.DynamicMeta
import hep.dataforge.meta.Meta
import hep.dataforge.meta.builder
import hep.dataforge.meta.update
import hep.dataforge.vis.common.VisualObject
import hep.dataforge.vis.common.findStyle
import hep.dataforge.vis.spatial.*
import hep.dataforge.vis.spatial.Material3D.Companion.MATERIAL_COLOR_KEY
import hep.dataforge.vis.spatial.Material3D.Companion.MATERIAL_OPACITY_KEY
import hep.dataforge.vis.spatial.VisualObject3D.Companion.VISIBLE_KEY
import kotlinx.html.dom.append
import kotlinx.html.js.div
import kotlinx.html.js.h4
@ -21,21 +16,13 @@ import kotlin.dom.clear
//FIXME something rotten in JS-Meta converter
fun Meta.toDynamic() = JSON.parse<dynamic>(toJson().toString())
fun Element.propertyEditor(item: VisualObject?) {
//TODO add node descriptor instead of configuring property selector
fun Element.propertyEditor(item: VisualObject?, propertySelector: (VisualObject) -> Meta = { it.config }) {
clear()
if (item != null) {
append {
card("Properties") {
val config: Meta = item.prototype.config
val metaToEdit = config.builder().apply {
VISIBLE_KEY to (item.visible ?: true)
if (item is VisualObject3D) {
MATERIAL_COLOR_KEY to (item.color ?: "#ffffff")
MATERIAL_OPACITY_KEY to (item.opacity ?: 1.0)
}
}
val dMeta: dynamic = metaToEdit.toDynamic()
val dMeta: dynamic = propertySelector(item).toDynamic()
val options: JSONEditorOptions = jsObject {
mode = "form"
onChangeJSON = { item.config.update(DynamicMeta(it.asDynamic())) }
@ -48,13 +35,17 @@ fun Element.propertyEditor(item: VisualObject?) {
card("Styles") {
item.styles.forEach { style ->
val styleMeta = item.findStyle(style)
h4("container") { +style.toString() }
h4("container") { +style }
if (styleMeta != null) {
div("container").apply {
val options: JSONEditorOptions = jsObject {
mode = "view"
}
JSONEditor(this, options, styleMeta.toDynamic())
JSONEditor(
this,
options,
styleMeta.toDynamic()
)
}
}
}
@ -62,4 +53,4 @@ fun Element.propertyEditor(item: VisualObject?) {
}
}
}
}
}

@ -1,4 +1,4 @@
package hep.dataforge.vis.fx.values
package hep.dataforge.vis.fx.editor
import hep.dataforge.meta.Meta
import hep.dataforge.names.Name
@ -44,6 +44,7 @@ class ColorValueChooser : ValueChooserBase<ColorPicker>() {
companion object : ValueChooser.Factory {
override val name: Name = "color".asName()
override fun invoke(meta: Meta): ValueChooser = ColorValueChooser()
override fun invoke(meta: Meta): ValueChooser =
ColorValueChooser()
}
}

@ -3,7 +3,7 @@
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package hep.dataforge.vis.fx.values
package hep.dataforge.vis.fx.editor
import hep.dataforge.meta.Meta
import hep.dataforge.meta.get
@ -54,7 +54,8 @@ class ComboBoxValueChooser(val values: Collection<Value>? = null) : ValueChooser
companion object : ValueChooser.Factory {
override val name: Name = "combo".asName()
override fun invoke(meta: Meta): ValueChooser = ComboBoxValueChooser(meta["values"].value?.list)
override fun invoke(meta: Meta): ValueChooser =
ComboBoxValueChooser(meta["values"].value?.list)
}
}

@ -3,14 +3,13 @@
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package hep.dataforge.vis.fx.meta
package hep.dataforge.vis.fx.editor
import hep.dataforge.context.Global
import hep.dataforge.descriptors.NodeDescriptor
import hep.dataforge.meta.Config
import hep.dataforge.names.NameToken
import hep.dataforge.vis.fx.dfIconView
import hep.dataforge.vis.fx.values.ValueChooser
import javafx.scene.control.*
import javafx.scene.control.cell.TextFieldTreeTableCell
import javafx.scene.layout.Priority
@ -29,8 +28,9 @@ class ConfigEditor(
val allowNew: Boolean = true,
title: String = "Configuration editor"
) : Fragment(title = title, icon = dfIconView) {
//TODO replace parameters by properties
constructor(config: Config, descriptor: NodeDescriptor, title: String = "Configuration editor") :
constructor(config: Config, descriptor: NodeDescriptor?, title: String = "Configuration editor") :
this(FXMeta.root(config, descriptor = descriptor), title = title)
override val root = borderpane {

@ -1,4 +1,4 @@
package hep.dataforge.vis.fx.meta
package hep.dataforge.vis.fx.editor
import hep.dataforge.descriptors.ItemDescriptor
import hep.dataforge.descriptors.NodeDescriptor

@ -14,7 +14,7 @@
* limitations under the License.
*/
package hep.dataforge.vis.fx.meta
package hep.dataforge.vis.fx.editor
import hep.dataforge.meta.Meta
import hep.dataforge.vis.fx.dfIconView

@ -3,7 +3,7 @@
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package hep.dataforge.vis.fx.values
package hep.dataforge.vis.fx.editor
import hep.dataforge.meta.Meta
import hep.dataforge.names.Name
@ -103,6 +103,7 @@ class TextValueChooser : ValueChooserBase<TextField>() {
companion object : ValueChooser.Factory {
override val name: Name = "text".asName()
override fun invoke(meta: Meta): ValueChooser = TextValueChooser()
override fun invoke(meta: Meta): ValueChooser =
TextValueChooser()
}
}

@ -3,7 +3,7 @@
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package hep.dataforge.vis.fx.values
package hep.dataforge.vis.fx.editor
import hep.dataforge.values.Value

@ -3,7 +3,7 @@
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package hep.dataforge.vis.fx.values
package hep.dataforge.vis.fx.editor
import hep.dataforge.context.Context
import hep.dataforge.context.Named
@ -87,7 +87,10 @@ interface ValueChooser {
val widgetType = descriptor.widgetType
val chooser: ValueChooser = when {
widgetType != null -> {
findWidgetByType(context, widgetType)?.invoke(
findWidgetByType(
context,
widgetType
)?.invoke(
descriptor.widget
) ?: TextValueChooser()
}
@ -105,7 +108,8 @@ interface ValueChooser {
descriptor: ValueDescriptor? = null,
setter: (Value) -> Unit
): ValueChooser {
val chooser = build(context, descriptor)
val chooser =
build(context, descriptor)
chooser.setDisplayValue(value.value ?: Null)
value.onChange {
chooser.setDisplayValue(it ?: Null)
@ -115,7 +119,11 @@ interface ValueChooser {
setter(result)
ValueCallbackResponse(true, result, "OK")
} else {
ValueCallbackResponse(false, value.value ?: Null, "Not allowed")
ValueCallbackResponse(
false,
value.value ?: Null,
"Not allowed"
)
}
}
return chooser

@ -3,7 +3,7 @@
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package hep.dataforge.vis.fx.values
package hep.dataforge.vis.fx.editor
import hep.dataforge.descriptors.ValueDescriptor
import hep.dataforge.values.Null

@ -0,0 +1,59 @@
package hep.dataforge.vis.fx.editor
import hep.dataforge.descriptors.NodeDescriptor
import hep.dataforge.meta.Config
import hep.dataforge.vis.common.VisualObject
import hep.dataforge.vis.common.findStyle
import javafx.beans.binding.Binding
import javafx.beans.property.SimpleObjectProperty
import javafx.scene.Node
import javafx.scene.Parent
import javafx.scene.layout.VBox
import tornadofx.*
class VisualObjectEditorFragment(val selector: (VisualObject) -> Config) : Fragment() {
val itemProperty = SimpleObjectProperty<VisualObject>()
var item: VisualObject? by itemProperty
val descriptorProperty = SimpleObjectProperty<NodeDescriptor>()
constructor(
item: VisualObject?,
descriptor: NodeDescriptor?,
selector: (VisualObject) -> Config = { it.config }
) : this(selector) {
this.item = item
this.descriptorProperty.set(descriptor)
}
private val configProperty: Binding<Config?> = itemProperty.objectBinding {
it?.let { selector(it) }
}
private val configEditorProperty: Binding<Node?> = configProperty.objectBinding(descriptorProperty) {
it?.let {
ConfigEditor(it, descriptorProperty.get()).root
}
}
private val styleBoxProperty: Binding<Node?> = configProperty.objectBinding() {
VBox().apply {
item?.styles?.forEach { styleName ->
val styleMeta = item?.findStyle(styleName)
if (styleMeta != null) {
titledpane(styleName, node = MetaViewer(styleMeta).root)
}
}
}
}
override val root: Parent = vbox {
titledpane("Properties", collapsible = false) {
contentProperty().bind(configEditorProperty)
}
titledpane("Styles", collapsible = false) {
visibleWhen(itemProperty.booleanBinding { it?.styles?.isNotEmpty() ?: false })
contentProperty().bind(styleBoxProperty)
}
}
}

@ -0,0 +1,33 @@
package hep.dataforge.vis.fx.editor
import hep.dataforge.vis.common.VisualGroup
import hep.dataforge.vis.common.VisualObject
import javafx.beans.property.SimpleObjectProperty
import javafx.scene.control.SelectionMode
import javafx.scene.control.TreeItem
import tornadofx.*
class VisualObjectTreeFragment : Fragment() {
val itemProperty = SimpleObjectProperty<VisualObject>()
var item: VisualObject? by itemProperty
val selectedProperty = SimpleObjectProperty<VisualObject>()
override val root = borderpane{
center = titledpane("Object tree") {
treeview<VisualObject> {
itemProperty.onChange { rootObject ->
if (rootObject != null) {
root = TreeItem(rootObject)
populate { item ->
(item.value as? VisualGroup)?.children?.values?.toList()
}
}
}
selectionModel.selectionMode = SelectionMode.SINGLE
val selectedValue = selectionModel.selectedItemProperty().objectBinding{it?.value}
selectedProperty.bind(selectedValue)
}
}
}
}

@ -4,9 +4,9 @@ import hep.dataforge.descriptors.NodeDescriptor
import hep.dataforge.meta.buildMeta
import hep.dataforge.meta.toConfig
import hep.dataforge.values.ValueType
import hep.dataforge.vis.fx.meta.ConfigEditor
import hep.dataforge.vis.fx.meta.FXMeta
import hep.dataforge.vis.fx.meta.MetaViewer
import hep.dataforge.vis.fx.editor.ConfigEditor
import hep.dataforge.vis.fx.editor.FXMeta
import hep.dataforge.vis.fx.editor.MetaViewer
import javafx.geometry.Orientation
import tornadofx.*

@ -16,7 +16,7 @@ import scientifik.gdml.*
import kotlin.random.Random
class GDMLTransformer(val root: GDML) {
private val materialCache = HashMap<GDMLMaterial, Meta>()
//private val materialCache = HashMap<GDMLMaterial, Meta>()
private val random = Random(222)
enum class Action {
@ -39,7 +39,7 @@ class GDMLTransformer(val root: GDML) {
var solidConfiguration: VisualObject3D.(parent: GDMLVolume, solid: GDMLSolid) -> Unit = { _, _ -> }
fun VisualObject.useStyle(name: String, builder: MetaBuilder.() -> Unit) {
fun VisualObject3D.useStyle(name: String, builder: MetaBuilder.() -> Unit) {
styleCache.getOrPut(name.toName()) {
buildMeta(builder)
}
@ -69,7 +69,7 @@ class GDMLTransformer(val root: GDML) {
final.prototypes = proto
styleCache.forEach {
final.styleSheet {
this[it.key.toString()] = it.value
define(it.key.toString(), it.value)
}
}
final.rotationOrder = RotationOrder.ZXY
@ -77,4 +77,4 @@ class GDMLTransformer(val root: GDML) {
return final
}
}
}

@ -256,6 +256,6 @@ fun GDML.toVisual(block: GDMLTransformer.() -> Unit = {}): VisualGroup3D {
*/
fun VisualGroup3D.gdml(gdml: GDML, key: String = "", transformer: GDMLTransformer.() -> Unit = {}) {
val visual = gdml.toVisual(transformer)
println(Visual3DPlugin.json.stringify(VisualGroup3D.serializer(), visual))
//println(Visual3DPlugin.json.stringify(VisualGroup3D.serializer(), visual))
set(key, visual)
}

File diff suppressed because one or more lines are too long

@ -6,8 +6,13 @@ import scientifik.gdml.GDML
import java.nio.file.Files
import java.nio.file.Path
fun VisualGroup3D.gdml(file: Path, key: String = "", transformer: GDMLTransformer.() -> Unit = {}) {
fun GDML.Companion.readFile(file: Path): GDML {
val xmlReader = StAXReader(Files.newInputStream(file), "UTF-8")
val gdml = GDML.format.parse(GDML.serializer(), xmlReader)
return GDML.format.parse(GDML.serializer(), xmlReader)
}
fun VisualGroup3D.gdml(file: Path, key: String = "", transformer: GDMLTransformer.() -> Unit = {}) {
val gdml = GDML.readFile(file)
gdml(gdml, key, transformer)
}
}

@ -28,7 +28,7 @@ kotlin {
}
jsMain {
dependencies {
api(project(":wrappers"))
// api(project(":wrappers"))
implementation(npm("three", "0.106.2"))
implementation(npm("@hi-level/three-csg", "1.0.6"))
}

@ -1,6 +1,6 @@
package hep.dataforge.vis.spatial.editor
package hep.dataforge.vis.spatial.three
import hep.dataforge.vis.spatial.three.ThreeCanvas
import hep.dataforge.vis.js.editor.card
import kotlinx.html.InputType
import kotlinx.html.dom.append
import kotlinx.html.js.div

@ -10,6 +10,9 @@ import hep.dataforge.vis.spatial.World.CAMERA_INITIAL_DISTANCE
import hep.dataforge.vis.spatial.World.CAMERA_INITIAL_X_ANGLE
import hep.dataforge.vis.spatial.World.CAMERA_INITIAL_Y_ANGLE
import hep.dataforge.vis.spatial.World.CAMERA_NEAR_CLIP
import javafx.application.Platform
import javafx.beans.property.ObjectProperty
import javafx.beans.property.SimpleObjectProperty
import javafx.event.EventHandler
import javafx.scene.*
import javafx.scene.input.KeyCode
@ -80,9 +83,26 @@ class FXCanvas3D(val plugin: FX3DPlugin, meta: Meta = EmptyMeta) :
center = canvas
}
val rootObjectProperty: ObjectProperty<VisualObject3D> = SimpleObjectProperty()
var rootObject: VisualObject3D? by rootObjectProperty
private val rootNodeProperty = rootObjectProperty.objectBinding {
it?.let { plugin.buildNode(it) }
}
init {
canvas.widthProperty().bind(root.widthProperty())
canvas.heightProperty().bind(root.heightProperty())
rootNodeProperty.addListener { _, oldValue: Node?, newValue: Node? ->
Platform.runLater {
if (oldValue != null) {
world.children.remove(oldValue)
}
if (newValue != null) {
world.children.add(newValue)
}
}
}
}
@ -167,8 +187,7 @@ class FXCanvas3D(val plugin: FX3DPlugin, meta: Meta = EmptyMeta) :
}
override fun render(obj: VisualObject3D, meta: Meta) {
val node = plugin.buildNode(obj) ?: kotlin.error("Can't render FX node for object $obj")
world.children.add(node)
rootObject = obj
}
companion object {

0
demo/build.gradle.kts Normal file

@ -0,0 +1,39 @@
import org.openjfx.gradle.JavaFXOptions
plugins {
id("scientifik.mpp")
id("org.openjfx.javafxplugin")
id("application")
}
kotlin {
jvm {
withJava()
}
js {
browser {
webpackTask {
sourceMaps = false
}
}
}
sourceSets {
commonMain {
dependencies {
api(project(":dataforge-vis-spatial"))
api(project(":dataforge-vis-spatial-gdml"))
}
}
}
}
application {
mainClassName = "hep.dataforge.vis.spatial.gdml.demo.GDMLDemoAppKt"
}
configure<JavaFXOptions> {
modules("javafx.controls")
}

@ -4,13 +4,15 @@ import hep.dataforge.context.Global
import hep.dataforge.js.Application
import hep.dataforge.js.objectTree
import hep.dataforge.js.startApplication
import hep.dataforge.meta.Meta
import hep.dataforge.meta.builder
import hep.dataforge.names.NameToken
import hep.dataforge.vis.spatial.*
import hep.dataforge.vis.spatial.Material3D.Companion.MATERIAL_COLOR_KEY
import hep.dataforge.vis.spatial.Material3D.Companion.MATERIAL_OPACITY_KEY
import hep.dataforge.vis.spatial.Visual3DPlugin
import hep.dataforge.vis.spatial.VisualGroup3D
import hep.dataforge.vis.spatial.VisualObject3D
import hep.dataforge.vis.spatial.editor.propertyEditor
import hep.dataforge.vis.spatial.editor.threeOutputConfig
import hep.dataforge.vis.spatial.VisualObject3D.Companion.VISIBLE_KEY
import hep.dataforge.vis.js.editor.propertyEditor
import hep.dataforge.vis.spatial.three.threeOutputConfig
import hep.dataforge.vis.spatial.gdml.GDMLTransformer
import hep.dataforge.vis.spatial.gdml.LUnit
import hep.dataforge.vis.spatial.gdml.toVisual
@ -153,7 +155,18 @@ private class GDMLDemoApp : Application {
output.camera.layers.set(0)
configElement.threeOutputConfig(output)
//tree.visualObjectTree(visual, editor::propertyEditor)
treeElement.objectTree(NameToken("World"), visual, editorElement::propertyEditor)
treeElement.objectTree(NameToken("World"), visual) {
editorElement.propertyEditor(it) {item->
val config: Meta = item.prototype.config
config.builder().apply {
VISIBLE_KEY to (item.visible ?: true)
if (item is VisualObject3D) {
MATERIAL_COLOR_KEY to (item.color ?: "#ffffff")
MATERIAL_OPACITY_KEY to (item.opacity ?: 1.0)
}
}
}
}
output.render(visual)

File diff suppressed because one or more lines are too long

@ -0,0 +1,78 @@
package hep.dataforge.vis.spatial.gdml.demo
import hep.dataforge.context.Global
import hep.dataforge.vis.fx.editor.VisualObjectEditorFragment
import hep.dataforge.vis.fx.editor.VisualObjectTreeFragment
import hep.dataforge.vis.spatial.Material3D
import hep.dataforge.vis.spatial.fx.FX3DPlugin
import hep.dataforge.vis.spatial.fx.FXCanvas3D
import hep.dataforge.vis.spatial.gdml.LUnit
import hep.dataforge.vis.spatial.gdml.readFile
import hep.dataforge.vis.spatial.gdml.toVisual
import hep.dataforge.vis.spatial.prototype
import javafx.geometry.Orientation
import javafx.scene.Parent
import javafx.stage.FileChooser
import scientifik.gdml.GDML
import tornadofx.*
class GDMLDemoApp : App(GDMLView::class)
class GDMLView : View() {
private val fx3d = Global.plugins.fetch(FX3DPlugin)
private val canvas = FXCanvas3D(fx3d)
private val treeFragment = VisualObjectTreeFragment().apply {
this.itemProperty.bind(canvas.rootObjectProperty)
}
private val propertyEditor = VisualObjectEditorFragment { it.prototype.config }.apply {
//TODO add descriptor here
itemProperty.bind(treeFragment.selectedProperty)
}
override val root: Parent = borderpane {
top {
buttonbar {
button("Load GDML") {
action {
val file = chooseFile("Select a GDML file", filters = gdmlFilter).firstOrNull()
if (file != null) {
val obj = GDML.readFile(file.toPath()).toVisual {
lUnit = LUnit.CM
solidConfiguration = { parent, solid ->
if(solid.name == "cave"){
setProperty(Material3D.MATERIAL_WIREFRAME_KEY, true)
}
if (parent.physVolumes.isNotEmpty()) {
useStyle("opaque") {
Material3D.MATERIAL_OPACITY_KEY put 0.3
}
}
}
}
canvas.render(obj)
}
}
}
}
}
center {
splitpane(Orientation.HORIZONTAL, treeFragment.root, canvas.root, propertyEditor.root) {
setDividerPositions(0.2, 0.6, 0.2)
}
}
}
companion object {
private val gdmlFilter = arrayOf(
FileChooser.ExtensionFilter("GDML", "*.gdml", "*.xml")
)
}
}
fun main() {
launch<GDMLDemoApp>()
}

@ -1,12 +1,9 @@
package hep.dataforge.vis.spatial.demo
import hep.dataforge.context.ContextBuilder
import hep.dataforge.context.Global
import hep.dataforge.js.Application
import hep.dataforge.js.startApplication
import hep.dataforge.vis.spatial.three.MeshThreeFactory.Companion.EDGES_ENABLED_KEY
import hep.dataforge.vis.spatial.three.MeshThreeFactory.Companion.WIREFRAME_ENABLED_KEY
import hep.dataforge.vis.spatial.three.ThreePlugin
import hep.dataforge.vis.spatial.x
import hep.dataforge.vis.spatial.y
import kotlinx.coroutines.GlobalScope

@ -4,14 +4,11 @@ import hep.dataforge.context.Global
import hep.dataforge.meta.Meta
import hep.dataforge.meta.buildMeta
import hep.dataforge.names.Name
import hep.dataforge.names.toName
import hep.dataforge.output.OutputManager
import hep.dataforge.output.Renderer
import hep.dataforge.vis.common.VisualObject
import hep.dataforge.vis.spatial.VisualGroup3D
import hep.dataforge.vis.spatial.fx.FX3DPlugin
import hep.dataforge.vis.spatial.fx.FXCanvas3D
import hep.dataforge.vis.spatial.render
import javafx.collections.FXCollections
import javafx.scene.Parent
import javafx.scene.control.Tab

@ -27,10 +27,11 @@ rootProject.name = "dataforge-vis"
include(
":dataforge-vis-common",
":wrappers",
// ":wrappers",
":dataforge-vis-spatial",
":dataforge-vis-spatial-gdml",
":spatial-demo"
":demo:spatial-showcase",
":demo:gdml"
)
//if(file("../dataforge-core").exists()) {