diff --git a/build.gradle.kts b/build.gradle.kts index f9ed11ca..b7ee4ffd 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,13 +1,10 @@ -import scientifik.useSerialization +import scientifik.fx +import scientifik.serialization -val dataforgeVersion by extra("0.1.5-dev-6") +val dataforgeVersion by extra("0.1.7") plugins { - val kotlinVersion = "1.3.61" - val toolsVersion = "0.3.2" - - kotlin("jvm") version kotlinVersion apply false - id("kotlin-dce-js") version kotlinVersion apply false + val toolsVersion = "0.4.2" id("scientifik.mpp") version toolsVersion apply false id("scientifik.jvm") version toolsVersion apply false id("scientifik.js") version toolsVersion apply false @@ -21,21 +18,23 @@ allprojects { maven("https://dl.bintray.com/pdvrieze/maven") maven("http://maven.jzy3d.org/releases") maven("https://kotlin.bintray.com/js-externals") + maven("https://kotlin.bintray.com/kotlin-js-wrappers/") // maven("https://dl.bintray.com/gbaldeck/kotlin") // maven("https://dl.bintray.com/rjaros/kotlin") } group = "hep.dataforge" - version = "0.1.1" -} - -subprojects{ - this.useSerialization() + version = "0.1.3-dev" } val githubProject by extra("dataforge-vis") val bintrayRepo by extra("dataforge") +val fxVersion by extra("14") subprojects { apply(plugin = "scientifik.publish") + serialization() + afterEvaluate { + fx(scientifik.FXModule.CONTROLS, version = fxVersion) + } } \ No newline at end of file diff --git a/dataforge-vis-common/build.gradle.kts b/dataforge-vis-common/build.gradle.kts index 6459c337..cf2d60c8 100644 --- a/dataforge-vis-common/build.gradle.kts +++ b/dataforge-vis-common/build.gradle.kts @@ -1,50 +1,49 @@ -import org.openjfx.gradle.JavaFXOptions -import scientifik.useSerialization - plugins { id("scientifik.mpp") - id("org.openjfx.javafxplugin") } val dataforgeVersion: String by rootProject.extra //val kvisionVersion: String by rootProject.extra("2.0.0-M1") -useSerialization() - kotlin { - jvm{ - withJava() - } - sourceSets { - commonMain{ + commonMain { dependencies { api("hep.dataforge:dataforge-output:$dataforgeVersion") } } - jvmMain{ + jvmMain { dependencies { - api("no.tornado:tornadofx:1.7.19") + api("no.tornado:tornadofx:1.7.20") //api("no.tornado:tornadofx-controlsfx:0.1.1") - api("de.jensd:fontawesomefx-fontawesome:4.7.0-11"){ + api("de.jensd:fontawesomefx-fontawesome:4.7.0-11") { exclude(group = "org.openjfx") } - api("de.jensd:fontawesomefx-commons:11.0"){ + api("de.jensd:fontawesomefx-commons:11.0") { exclude(group = "org.openjfx") } } } - jsMain{ + jsMain { dependencies { api("hep.dataforge:dataforge-output-html:$dataforgeVersion") - //api(npm("bootstrap","4.4.1")) - implementation(npm("jsoneditor")) - implementation(npm("file-saver")) + + //React, React DOM + Wrappers (chapter 3) + api("org.jetbrains:kotlin-react:16.13.0-pre.94-kotlin-1.3.70") + api("org.jetbrains:kotlin-react-dom:16.13.0-pre.94-kotlin-1.3.70") + api(npm("react", "16.13.0")) + api(npm("react-dom", "16.13.0")) + + //Kotlin Styled (chapter 3) + api("org.jetbrains:kotlin-styled:1.0.0-pre.94-kotlin-1.3.70") + api(npm("styled-components")) + api(npm("inline-style-prefixer")) + + + api(npm("bootstrap","4.3.1")) + //api(npm("jsoneditor", "8.6.1")) + api(npm("file-saver","2.0.2")) } } } -} - -configure { - modules("javafx.controls") -} +} \ No newline at end of file diff --git a/dataforge-vis-common/src/commonMain/kotlin/hep/dataforge/vis/common/AbstractVisualGroup.kt b/dataforge-vis-common/src/commonMain/kotlin/hep/dataforge/vis/AbstractVisualGroup.kt similarity index 63% rename from dataforge-vis-common/src/commonMain/kotlin/hep/dataforge/vis/common/AbstractVisualGroup.kt rename to dataforge-vis-common/src/commonMain/kotlin/hep/dataforge/vis/AbstractVisualGroup.kt index a0af25b7..d130b5c7 100644 --- a/dataforge-vis-common/src/commonMain/kotlin/hep/dataforge/vis/common/AbstractVisualGroup.kt +++ b/dataforge-vis-common/src/commonMain/kotlin/hep/dataforge/vis/AbstractVisualGroup.kt @@ -1,4 +1,4 @@ -package hep.dataforge.vis.common +package hep.dataforge.vis import hep.dataforge.meta.MetaItem import hep.dataforge.names.Name @@ -20,6 +20,17 @@ abstract class AbstractVisualGroup : AbstractVisualObject(), MutableVisualGroup */ abstract override val children: Map + abstract override var styleSheet: StyleSheet? + protected set + + /** + * Update or create stylesheet + */ + fun styleSheet(block: StyleSheet.() -> Unit) { + val res = styleSheet ?: StyleSheet(this).also { styleSheet = it } + res.block() + } + override fun propertyChanged(name: Name, before: MetaItem<*>?, after: MetaItem<*>?) { super.propertyChanged(name, before, after) forEach { @@ -37,7 +48,12 @@ abstract class AbstractVisualGroup : AbstractVisualObject(), MutableVisualGroup * Add listener for children change */ override fun onChildrenChange(owner: Any?, action: (Name, VisualObject?) -> Unit) { - structureChangeListeners.add(StructureChangeListeners(owner, action)) + structureChangeListeners.add( + StructureChangeListeners( + owner, + action + ) + ) } /** @@ -68,12 +84,41 @@ abstract class AbstractVisualGroup : AbstractVisualObject(), MutableVisualGroup * Add a static child. Statics could not be found by name, removed or replaced */ protected open fun addStatic(child: VisualObject) = - setChild(NameToken("@static(${child.hashCode()})"), child) + set(NameToken("@static(${child.hashCode()})").asName(), child) + + protected abstract fun createGroup(): AbstractVisualGroup + + /** + * Set this node as parent for given node + */ + protected fun attach(child: VisualObject) { + if (child.parent == null) { + child.parent = this + } else if (child.parent !== this) { + error("Can't reassign existing parent for $child") + } + } /** * Recursively create a child group */ - protected abstract fun createGroup(name: Name): MutableVisualGroup + private fun createGroups(name: Name): AbstractVisualGroup { + return when { + name.isEmpty() -> error("Should be unreachable") + name.length == 1 -> { + val token = name.first()!! + when (val current = children[token]) { + null -> createGroup().also { child -> + attach(child) + setChild(token, child) + } + is AbstractVisualGroup -> current + else -> error("Can't create group with name $name because it exists and not a group") + } + } + else -> createGroups(name.first()!!.asName()).createGroups(name.cutFirst()) + } + } /** * Add named or unnamed child to the group. If key is null the child is considered unnamed. Both key and value are not @@ -91,16 +136,17 @@ abstract class AbstractVisualGroup : AbstractVisualObject(), MutableVisualGroup if (child == null) { removeChild(token) } else { + attach(child) setChild(token, child) } } else -> { //TODO add safety check - val parent = (get(name.cutLast()) as? MutableVisualGroup) ?: createGroup(name.cutLast()) + val parent = (get(name.cutLast()) as? MutableVisualGroup) ?: createGroups(name.cutLast()) parent[name.last()!!.asName()] = child } } - structureChangeListeners.forEach { it.callback(name, child) } + childrenChanged(name, child) } } \ No newline at end of file diff --git a/dataforge-vis-common/src/commonMain/kotlin/hep/dataforge/vis/common/AbstractVisualObject.kt b/dataforge-vis-common/src/commonMain/kotlin/hep/dataforge/vis/AbstractVisualObject.kt similarity index 90% rename from dataforge-vis-common/src/commonMain/kotlin/hep/dataforge/vis/common/AbstractVisualObject.kt rename to dataforge-vis-common/src/commonMain/kotlin/hep/dataforge/vis/AbstractVisualObject.kt index 5487a304..e355fa94 100644 --- a/dataforge-vis-common/src/commonMain/kotlin/hep/dataforge/vis/common/AbstractVisualObject.kt +++ b/dataforge-vis-common/src/commonMain/kotlin/hep/dataforge/vis/AbstractVisualObject.kt @@ -1,9 +1,10 @@ -package hep.dataforge.vis.common +package hep.dataforge.vis import hep.dataforge.meta.* import hep.dataforge.names.Name import hep.dataforge.names.asName -import hep.dataforge.vis.common.VisualObject.Companion.STYLE_KEY +import hep.dataforge.values.Value +import hep.dataforge.vis.VisualObject.Companion.STYLE_KEY import kotlinx.serialization.Transient internal data class PropertyListener( @@ -14,7 +15,7 @@ internal data class PropertyListener( abstract class AbstractVisualObject : VisualObject { @Transient - override var parent: VisualObject? = null + override var parent: VisualGroup? = null protected abstract var properties: Config? @@ -22,7 +23,7 @@ abstract class AbstractVisualObject : VisualObject { get() = properties?.get(STYLE_KEY).stringList set(value) { //val allStyles = (field + value).distinct() - setProperty(STYLE_KEY, value) + setProperty(STYLE_KEY, Value.of(value)) updateStyles(value) } @@ -66,7 +67,7 @@ abstract class AbstractVisualObject : VisualObject { private var styleCache: Meta? = null /** - * Collect all styles for this object in a laminate + * Collect all styles for this object in a single cached meta */ protected val mergedStyles: Meta get() = styleCache ?: findAllStyles().merge().also { diff --git a/dataforge-vis-common/src/commonMain/kotlin/hep/dataforge/vis/common/Colors.kt b/dataforge-vis-common/src/commonMain/kotlin/hep/dataforge/vis/Colors.kt similarity index 97% rename from dataforge-vis-common/src/commonMain/kotlin/hep/dataforge/vis/common/Colors.kt rename to dataforge-vis-common/src/commonMain/kotlin/hep/dataforge/vis/Colors.kt index 3335c086..b91dbcff 100644 --- a/dataforge-vis-common/src/commonMain/kotlin/hep/dataforge/vis/common/Colors.kt +++ b/dataforge-vis-common/src/commonMain/kotlin/hep/dataforge/vis/Colors.kt @@ -1,6 +1,9 @@ -package hep.dataforge.vis.common +package hep.dataforge.vis -import hep.dataforge.meta.* +import hep.dataforge.meta.Meta +import hep.dataforge.meta.MetaItem +import hep.dataforge.meta.get +import hep.dataforge.meta.number import hep.dataforge.values.ValueType import hep.dataforge.values.int import kotlin.math.max @@ -234,7 +237,7 @@ object Colors { /** * Convert three bytes representing color to Meta */ - fun rgbToMeta(r: UByte, g: UByte, b: UByte): Meta = buildMeta { + fun rgbToMeta(r: UByte, g: UByte, b: UByte): Meta = Meta { RED_KEY put r.toInt() GREEN_KEY put g.toInt() BLUE_KEY put b.toInt() diff --git a/dataforge-vis-common/src/commonMain/kotlin/hep/dataforge/vis/SimpleVisualGroup.kt b/dataforge-vis-common/src/commonMain/kotlin/hep/dataforge/vis/SimpleVisualGroup.kt new file mode 100644 index 00000000..468a5264 --- /dev/null +++ b/dataforge-vis-common/src/commonMain/kotlin/hep/dataforge/vis/SimpleVisualGroup.kt @@ -0,0 +1,31 @@ +package hep.dataforge.vis + +import hep.dataforge.meta.Config +import hep.dataforge.names.NameToken +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + + +@Serializable +@SerialName("group") +class SimpleVisualGroup : AbstractVisualGroup() { + + override var styleSheet: StyleSheet? = null + + //FIXME to be lifted to AbstractVisualGroup after https://github.com/Kotlin/kotlinx.serialization/issues/378 is fixed + override var properties: Config? = null + + @SerialName("children") + private val _children = HashMap() + override val children: Map get() = _children + + override fun removeChild(token: NameToken) { + _children.remove(token)?.apply { parent = null } + } + + override fun setChild(token: NameToken, child: VisualObject) { + _children[token] = child + } + + override fun createGroup(): SimpleVisualGroup = SimpleVisualGroup() +} \ No newline at end of file diff --git a/dataforge-vis-common/src/commonMain/kotlin/hep/dataforge/vis/common/StyleSheet.kt b/dataforge-vis-common/src/commonMain/kotlin/hep/dataforge/vis/StyleSheet.kt similarity index 64% rename from dataforge-vis-common/src/commonMain/kotlin/hep/dataforge/vis/common/StyleSheet.kt rename to dataforge-vis-common/src/commonMain/kotlin/hep/dataforge/vis/StyleSheet.kt index 7b70a0dc..b244c410 100644 --- a/dataforge-vis-common/src/commonMain/kotlin/hep/dataforge/vis/common/StyleSheet.kt +++ b/dataforge-vis-common/src/commonMain/kotlin/hep/dataforge/vis/StyleSheet.kt @@ -1,18 +1,19 @@ @file:UseSerializers(MetaSerializer::class) -package hep.dataforge.vis.common +package hep.dataforge.vis -import hep.dataforge.io.serialization.MetaSerializer import hep.dataforge.meta.* import hep.dataforge.names.Name import hep.dataforge.names.asName import kotlinx.serialization.* +import kotlinx.serialization.builtins.MapSerializer +import kotlinx.serialization.builtins.serializer /** * A container for styles */ @Serializable -class StyleSheet() { +class StyleSheet private constructor(private val styleMap: MutableMap = LinkedHashMap()) { @Transient internal var owner: VisualObject? = null @@ -20,12 +21,10 @@ class StyleSheet() { this.owner = owner } - private val styleMap = HashMap() - val items: Map get() = styleMap operator fun get(key: String): Meta? { - return styleMap[key] ?: (owner?.parent as? VisualGroup)?.styleSheet?.get(key) + return styleMap[key] ?: owner?.parent?.styleSheet?.get(key) } /** @@ -46,20 +45,23 @@ class StyleSheet() { } operator fun set(key: String, builder: MetaBuilder.() -> Unit) { - val newStyle = get(key)?.let { buildMeta(it, builder) } ?: buildMeta(builder) + val newStyle = get(key)?.edit(builder) ?: Meta(builder) set(key, newStyle.seal()) } - companion object: KSerializer{ - override val descriptor: SerialDescriptor - get() = TODO("Not yet implemented") + @Serializer(StyleSheet::class) + companion object : KSerializer { + private val mapSerializer = MapSerializer(String.serializer(), MetaSerializer) + override val descriptor: SerialDescriptor get() = mapSerializer.descriptor + override fun deserialize(decoder: Decoder): StyleSheet { - TODO("Not yet implemented") + val map = mapSerializer.deserialize(decoder) + return StyleSheet(map as? MutableMap ?: LinkedHashMap(map)) } - override fun serialize(encoder: Encoder, obj: StyleSheet) { - TODO("Not yet implemented") + override fun serialize(encoder: Encoder, value: StyleSheet) { + mapSerializer.serialize(encoder, value.items) } } diff --git a/dataforge-vis-common/src/commonMain/kotlin/hep/dataforge/vis/common/Visual.kt b/dataforge-vis-common/src/commonMain/kotlin/hep/dataforge/vis/Visual.kt similarity index 95% rename from dataforge-vis-common/src/commonMain/kotlin/hep/dataforge/vis/common/Visual.kt rename to dataforge-vis-common/src/commonMain/kotlin/hep/dataforge/vis/Visual.kt index a469ac63..8aeb32a4 100644 --- a/dataforge-vis-common/src/commonMain/kotlin/hep/dataforge/vis/common/Visual.kt +++ b/dataforge-vis-common/src/commonMain/kotlin/hep/dataforge/vis/Visual.kt @@ -1,4 +1,4 @@ -package hep.dataforge.vis.common +package hep.dataforge.vis import hep.dataforge.context.* import hep.dataforge.meta.Meta @@ -31,7 +31,8 @@ class Visual(meta: Meta) : AbstractPlugin(meta) { override val tag: PluginTag = PluginTag(name = "visual", group = PluginTag.DATAFORGE_GROUP) override val type: KClass = Visual::class - override fun invoke(meta: Meta, context: Context): Visual = Visual(meta) + override fun invoke(meta: Meta, context: Context): Visual = + Visual(meta) const val VISUAL_FACTORY_TYPE = "visual.factory" } diff --git a/dataforge-vis-common/src/commonMain/kotlin/hep/dataforge/vis/common/VisualGroup.kt b/dataforge-vis-common/src/commonMain/kotlin/hep/dataforge/vis/VisualGroup.kt similarity index 95% rename from dataforge-vis-common/src/commonMain/kotlin/hep/dataforge/vis/common/VisualGroup.kt rename to dataforge-vis-common/src/commonMain/kotlin/hep/dataforge/vis/VisualGroup.kt index c3f497bd..d077a269 100644 --- a/dataforge-vis-common/src/commonMain/kotlin/hep/dataforge/vis/common/VisualGroup.kt +++ b/dataforge-vis-common/src/commonMain/kotlin/hep/dataforge/vis/VisualGroup.kt @@ -1,4 +1,4 @@ -package hep.dataforge.vis.common +package hep.dataforge.vis import hep.dataforge.names.* import hep.dataforge.provider.Provider @@ -6,7 +6,8 @@ import hep.dataforge.provider.Provider /** * Represents a group of [VisualObject] instances */ -interface VisualGroup : Provider, Iterable, VisualObject { +interface VisualGroup : Provider, Iterable, + VisualObject { /** * A map of top level named children */ diff --git a/dataforge-vis-common/src/commonMain/kotlin/hep/dataforge/vis/common/VisualObject.kt b/dataforge-vis-common/src/commonMain/kotlin/hep/dataforge/vis/VisualObject.kt similarity index 83% rename from dataforge-vis-common/src/commonMain/kotlin/hep/dataforge/vis/common/VisualObject.kt rename to dataforge-vis-common/src/commonMain/kotlin/hep/dataforge/vis/VisualObject.kt index 6aad894a..b757fcb3 100644 --- a/dataforge-vis-common/src/commonMain/kotlin/hep/dataforge/vis/common/VisualObject.kt +++ b/dataforge-vis-common/src/commonMain/kotlin/hep/dataforge/vis/VisualObject.kt @@ -1,11 +1,15 @@ -package hep.dataforge.vis.common +package hep.dataforge.vis -import hep.dataforge.meta.* +import hep.dataforge.meta.Configurable +import hep.dataforge.meta.Laminate +import hep.dataforge.meta.Meta +import hep.dataforge.meta.MetaItem import hep.dataforge.names.Name import hep.dataforge.names.asName import hep.dataforge.names.toName import hep.dataforge.provider.Type -import hep.dataforge.vis.common.VisualObject.Companion.TYPE +import hep.dataforge.vis.VisualObject.Companion.TYPE +import kotlinx.serialization.PolymorphicSerializer import kotlinx.serialization.Transient //private fun Laminate.withTop(meta: Meta): Laminate = Laminate(listOf(meta) + layers) @@ -21,24 +25,19 @@ interface VisualObject : Configurable { * The parent object of this one. If null, this one is a root. */ @Transient - var parent: VisualObject? + var parent: VisualGroup? /** * All properties including styles and prototypes if present, but without inheritance */ fun allProperties(): Laminate - /** - * Set property for this object - */ - fun setProperty(name: Name, value: Any?) { - config[name] = value - } - /** * Get property including or excluding parent properties */ - fun getProperty(name: Name, inherit: Boolean = true): MetaItem<*>? + fun getProperty(name: Name, inherit: Boolean): MetaItem<*>? + + override fun getProperty(name: Name): MetaItem<*>? = getProperty(name, true) /** * Trigger property invalidation event. If [name] is empty, notify that the whole object is changed @@ -66,6 +65,10 @@ interface VisualObject : Configurable { const val TYPE = "visual" val STYLE_KEY = "@style".asName() + private val VISUAL_OBJECT_SERIALIZER = PolymorphicSerializer(VisualObject::class) + + fun serializer() = VISUAL_OBJECT_SERIALIZER + //const val META_KEY = "@meta" //const val TAGS_KEY = "@tags" @@ -77,11 +80,6 @@ interface VisualObject : Configurable { */ fun VisualObject.getProperty(key: String, inherit: Boolean = true): MetaItem<*>? = getProperty(key.toName(), inherit) -/** - * Set [VisualObject] property using key as a String - */ -fun VisualObject.setProperty(key: String, value: Any?) = setProperty(key.toName(), value) - /** * 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/dataforge-vis-common/src/commonMain/kotlin/hep/dataforge/vis/common/VisualObjectDelegate.kt b/dataforge-vis-common/src/commonMain/kotlin/hep/dataforge/vis/VisualObjectDelegate.kt similarity index 98% rename from dataforge-vis-common/src/commonMain/kotlin/hep/dataforge/vis/common/VisualObjectDelegate.kt rename to dataforge-vis-common/src/commonMain/kotlin/hep/dataforge/vis/VisualObjectDelegate.kt index ec16f977..d0798522 100644 --- a/dataforge-vis-common/src/commonMain/kotlin/hep/dataforge/vis/common/VisualObjectDelegate.kt +++ b/dataforge-vis-common/src/commonMain/kotlin/hep/dataforge/vis/VisualObjectDelegate.kt @@ -1,4 +1,4 @@ -package hep.dataforge.vis.common +package hep.dataforge.vis import hep.dataforge.meta.* import hep.dataforge.names.Name @@ -105,8 +105,8 @@ fun VisualObject.int(default: Int, name: Name? = null, inherited: Boolean = fals inline fun > VisualObject.enum(default: E, name: Name? = null, inherited: Boolean = false) = - VisualObjectDelegateWrapper(this, name, default, inherited) { - item -> item.string?.let { enumValueOf(it) } + VisualObjectDelegateWrapper(this, name, default, inherited) { item -> + item.string?.let { enumValueOf(it) } } //merge properties diff --git a/dataforge-vis-common/src/commonMain/kotlin/hep/dataforge/vis/common/valueWidget.kt b/dataforge-vis-common/src/commonMain/kotlin/hep/dataforge/vis/common/valueWidget.kt deleted file mode 100644 index 8c45686f..00000000 --- a/dataforge-vis-common/src/commonMain/kotlin/hep/dataforge/vis/common/valueWidget.kt +++ /dev/null @@ -1,22 +0,0 @@ -package hep.dataforge.vis.common - -import hep.dataforge.descriptors.ValueDescriptor -import hep.dataforge.meta.* - -/** - * Extension property to access the "widget" key of [ValueDescriptor] - */ -var ValueDescriptor.widget: Meta - get() = this.config["widget"].node?: EmptyMeta - set(value) { - this.config["widget"] = value - } - -/** - * Extension property to access the "widget.type" key of [ValueDescriptor] - */ -var ValueDescriptor.widgetType: String? - get() = this["widget.type"].string - set(value) { - this.config["widget.type"] = value - } \ No newline at end of file diff --git a/dataforge-vis-common/src/commonMain/kotlin/hep/dataforge/vis/valueWidget.kt b/dataforge-vis-common/src/commonMain/kotlin/hep/dataforge/vis/valueWidget.kt new file mode 100644 index 00000000..80e44a35 --- /dev/null +++ b/dataforge-vis-common/src/commonMain/kotlin/hep/dataforge/vis/valueWidget.kt @@ -0,0 +1,23 @@ +package hep.dataforge.vis + +import hep.dataforge.meta.* +import hep.dataforge.meta.descriptors.ValueDescriptor +import hep.dataforge.values.asValue + +/** + * Extension property to access the "widget" key of [ValueDescriptor] + */ +var ValueDescriptor.widget: Meta + get() = getProperty("widget").node ?: Meta.EMPTY + set(value) { + setProperty("widget", value) + } + +/** + * Extension property to access the "widget.type" key of [ValueDescriptor] + */ +var ValueDescriptor.widgetType: String? + get() = getProperty("widget.type").string + set(value) { + setProperty("widget.type", value?.asValue()) + } \ No newline at end of file diff --git a/dataforge-vis-common/src/jsMain/kotlin/hep/dataforge/js/react.kt b/dataforge-vis-common/src/jsMain/kotlin/hep/dataforge/js/react.kt new file mode 100644 index 00000000..2611e7db --- /dev/null +++ b/dataforge-vis-common/src/jsMain/kotlin/hep/dataforge/js/react.kt @@ -0,0 +1,17 @@ +package hep.dataforge.js + +import react.RComponent +import kotlin.properties.ReadWriteProperty +import kotlin.reflect.KProperty + +fun RComponent<*, *>.initState(init: () -> T): ReadWriteProperty, T> = + object : ReadWriteProperty, T> { + val pair = react.useState(init) + override fun getValue(thisRef: RComponent<*, *>, property: KProperty<*>): T { + return pair.first + } + + override fun setValue(thisRef: RComponent<*, *>, property: KProperty<*>, value: T) { + pair.second(value) + } + } \ No newline at end of file diff --git a/dataforge-vis-common/src/jsMain/kotlin/hep/dataforge/vis/editor/ConfigEditorComponent.kt b/dataforge-vis-common/src/jsMain/kotlin/hep/dataforge/vis/editor/ConfigEditorComponent.kt new file mode 100644 index 00000000..ff1e797f --- /dev/null +++ b/dataforge-vis-common/src/jsMain/kotlin/hep/dataforge/vis/editor/ConfigEditorComponent.kt @@ -0,0 +1,184 @@ +package hep.dataforge.vis.editor + +import hep.dataforge.meta.* +import hep.dataforge.meta.descriptors.NodeDescriptor +import hep.dataforge.meta.descriptors.defaultItem +import hep.dataforge.meta.descriptors.get +import hep.dataforge.names.Name +import hep.dataforge.names.NameToken +import hep.dataforge.names.plus +import hep.dataforge.values.asValue +import kotlinx.html.InputType +import kotlinx.html.classes +import kotlinx.html.js.onChangeFunction +import kotlinx.html.js.onClickFunction +import org.w3c.dom.Element +import org.w3c.dom.events.Event +import react.RBuilder +import react.RComponent +import react.RProps +import react.dom.* +import react.setState + +interface ConfigEditorProps : RProps { + /** + * Root config object - always non null + */ + var root: Config + + /** + * Full path to the displayed node in [root]. Could be empty + */ + var name: Name + + /** + * Root default + */ + var default: Meta? + + /** + * Root descriptor + */ + var descriptor: NodeDescriptor? + + var listen: Boolean +} + +class ConfigEditorComponent : RComponent() { + + override fun TreeState.init() { + expanded = false + } + + override fun componentDidMount() { + if (props.listen) { + props.root.onChange(this) { name, _, _ -> + if (name == props.name) { + forceUpdate() + } + } + } + } + + override fun componentWillUnmount() { + props.root.removeListener(this) + } + + private val onClick: (Event) -> Unit = { + setState { + expanded = !expanded + } + } + + + override fun RBuilder.render() { + val item = props.root[props.name] + val descriptorItem = props.descriptor?.get(props.name) + val defaultItem = props.default?.get(props.name) + val actualItem = item ?: defaultItem ?: descriptorItem?.defaultItem() + val token = props.name.last() + + div("d-inline-block text-truncate") { + when (actualItem) { + null -> { + } + is MetaItem.ValueItem -> { + i("tree-caret") { } + } + is MetaItem.NodeItem -> { + i("tree-caret fa fa-caret-right") { + attrs { + if (state.expanded) { + classes += "rotate" + } + onClickFunction = onClick + } + } + } + } + label("tree-label") { + +token.toString() + attrs { + if (item == null) { + classes += "tree-label-inactive" + } + } + } + + if (actualItem is MetaItem.NodeItem && state.expanded) { + ul("tree") { + val keys = buildList { + item?.node?.items?.keys?.let { addAll(it) } + defaultItem?.node?.items?.keys?.let { addAll(it) } + (descriptorItem as? NodeDescriptor)?.items?.keys?.forEach { + add(NameToken(it)) + } + } + keys.forEach { token -> + li("tree-item") { + child(ConfigEditorComponent::class) { + attrs { + root = props.root + name = props.name + token + this.default = props.default + this.descriptor = props.descriptor + listen = false + } + } + } + } + } + } else if (actualItem is MetaItem.ValueItem) { + div("row") { + div("col") { + label("tree-label") { + +token.toString() + } + } + div("col") { + input(type = InputType.text) { + attrs { + value = actualItem.value.toString() + onChangeFunction = { + try { + props.root.setValue(props.name, value.asValue()) + } catch (ex: Exception) { + console.error("Can't set config property $name to $value") + } + } + } + } + //+actualItem.value.toString() + } + } + } + } + } + +} + +fun Element.configEditor(config: Config, descriptor: NodeDescriptor? = null, default: Meta? = null) { + render(this) { + child(ConfigEditorComponent::class) { + attrs { + root = config + name = Name.EMPTY + this.descriptor = descriptor + this.default = default + listen = true + } + } + } +} + +fun RBuilder.configEditor(config: Config, descriptor: NodeDescriptor? = null, default: Meta? = null) { + child(ConfigEditorComponent::class) { + attrs { + root = config + name = Name.EMPTY + this.descriptor = descriptor + this.default = default + listen = true + } + } +} diff --git a/dataforge-vis-common/src/jsMain/kotlin/hep/dataforge/vis/editor/MetaViewerComponent.kt b/dataforge-vis-common/src/jsMain/kotlin/hep/dataforge/vis/editor/MetaViewerComponent.kt new file mode 100644 index 00000000..77a2d4b7 --- /dev/null +++ b/dataforge-vis-common/src/jsMain/kotlin/hep/dataforge/vis/editor/MetaViewerComponent.kt @@ -0,0 +1,84 @@ +package hep.dataforge.vis.editor + +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.RBuilder +import react.RComponent +import react.RProps +import react.dom.* +import react.setState + +interface MetaViewerProps : RProps { + var name: NameToken + var meta: Meta + var descriptor: NodeDescriptor? +} + +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("objTree-caret") { + attrs { + if (state.expanded) { + classes += "objTree-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/dataforge-vis-common/src/jsMain/kotlin/hep/dataforge/vis/editor/ObjectTreeComponent.kt b/dataforge-vis-common/src/jsMain/kotlin/hep/dataforge/vis/editor/ObjectTreeComponent.kt new file mode 100644 index 00000000..97047170 --- /dev/null +++ b/dataforge-vis-common/src/jsMain/kotlin/hep/dataforge/vis/editor/ObjectTreeComponent.kt @@ -0,0 +1,111 @@ +package hep.dataforge.vis.editor + +import hep.dataforge.names.Name +import hep.dataforge.names.plus +import hep.dataforge.vis.VisualGroup +import hep.dataforge.vis.VisualObject +import hep.dataforge.vis.isEmpty +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.* + +interface ObjectTreeProps : RProps { + var name: Name + var obj: VisualObject + var clickCallback: (Name) -> Unit +} + +interface TreeState : RState { + var expanded: Boolean +} + +class ObjectTreeComponent : RComponent() { + + override fun TreeState.init() { + expanded = false + } + + private val onClick: (Event) -> Unit = { + setState { + expanded = !expanded + } + } + + override fun RBuilder.render() { + val token = props.name.last()?.toString() ?: "World" + val obj = props.obj + + //display as node if any child is visible + if (obj is VisualGroup && obj.children.keys.any { !it.body.startsWith("@") }) { + div("d-inline-block text-truncate") { + span("objTree-caret") { + attrs { + if (state.expanded) { + classes += "objTree-caret-down" + } + onClickFunction = onClick + } + } + label("objTree-label") { + +token + attrs { + onClickFunction = { props.clickCallback(props.name) } + } + } + } + if (state.expanded) { + ul("objTree-subtree") { + obj.children.entries + .filter { !it.key.toString().startsWith("@") } // ignore statics and other hidden children + .sortedBy { (it.value as? VisualGroup)?.isEmpty ?: true } + .forEach { (childToken, child) -> + li { + child(ObjectTreeComponent::class) { + attrs { + name = props.name + childToken + this.obj = child + clickCallback = props.clickCallback + } + } + } + } + } + } + } else { + div("d-inline-block text-truncate") { + span("objTree-leaf") {} + label("objTree-label") { + +token + attrs { + onClickFunction = { props.clickCallback(props.name) } + } + } + } + } + } +} + +fun RBuilder.objectTree( + obj: VisualObject, + clickCallback: (Name) -> Unit = {} +) = card("Object tree") { + child(ObjectTreeComponent::class) { + attrs { + name = Name.EMPTY + this.obj = obj + this.clickCallback = clickCallback + } + } +} + +fun Element.objectTree( + obj: VisualObject, + clickCallback: (Name) -> Unit = {} +) { + render(this) { + objectTree(obj, clickCallback) + } +} \ No newline at end of file diff --git a/dataforge-vis-common/src/jsMain/kotlin/hep/dataforge/vis/js/editor/bootstrap.kt b/dataforge-vis-common/src/jsMain/kotlin/hep/dataforge/vis/editor/bootstrap.kt similarity index 86% rename from dataforge-vis-common/src/jsMain/kotlin/hep/dataforge/vis/js/editor/bootstrap.kt rename to dataforge-vis-common/src/jsMain/kotlin/hep/dataforge/vis/editor/bootstrap.kt index 171aa86d..02149034 100644 --- a/dataforge-vis-common/src/jsMain/kotlin/hep/dataforge/vis/js/editor/bootstrap.kt +++ b/dataforge-vis-common/src/jsMain/kotlin/hep/dataforge/vis/editor/bootstrap.kt @@ -1,8 +1,12 @@ -package hep.dataforge.vis.js.editor +package hep.dataforge.vis.editor import kotlinx.html.* import kotlinx.html.js.div import org.w3c.dom.HTMLElement +import react.RBuilder +import react.ReactElement +import react.dom.div +import react.dom.h3 inline fun TagConsumer.card(title: String, crossinline block: TagConsumer.() -> Unit) { div("card w-100") { @@ -13,6 +17,14 @@ inline fun TagConsumer.card(title: String, crossinline block: TagCo } } +inline fun RBuilder.card(title: String, crossinline block: RBuilder.() -> Unit): ReactElement = div("card w-100") { + div("card-body") { + h3(classes = "card-title") { +title } + block() + } +} + + fun TagConsumer.accordion(id: String, elements: Map Unit>) { div("container-fluid") { div("accordion") { diff --git a/dataforge-vis-common/src/jsMain/kotlin/hep/dataforge/vis/js/editor/jsTree.kt b/dataforge-vis-common/src/jsMain/kotlin/hep/dataforge/vis/editor/jsTree.kt similarity index 84% rename from dataforge-vis-common/src/jsMain/kotlin/hep/dataforge/vis/js/editor/jsTree.kt rename to dataforge-vis-common/src/jsMain/kotlin/hep/dataforge/vis/editor/jsTree.kt index dde67544..a9c876ae 100644 --- a/dataforge-vis-common/src/jsMain/kotlin/hep/dataforge/vis/js/editor/jsTree.kt +++ b/dataforge-vis-common/src/jsMain/kotlin/hep/dataforge/vis/editor/jsTree.kt @@ -1,10 +1,10 @@ -package hep.dataforge.vis.js.editor +package hep.dataforge.vis.editor import hep.dataforge.names.Name import hep.dataforge.names.plus -import hep.dataforge.vis.common.VisualGroup -import hep.dataforge.vis.common.VisualObject -import hep.dataforge.vis.common.isEmpty +import hep.dataforge.vis.VisualGroup +import hep.dataforge.vis.VisualObject +import hep.dataforge.vis.isEmpty import kotlinx.html.TagConsumer import kotlinx.html.dom.append import kotlinx.html.js.* @@ -13,18 +13,18 @@ import org.w3c.dom.HTMLElement import org.w3c.dom.HTMLSpanElement import kotlin.dom.clear -fun Element.displayObjectTree( - obj: VisualObject, - clickCallback: (Name) -> Unit = {} -) { - clear() - append { - card("Object tree") { - subTree(Name.EMPTY, obj, clickCallback) - } - } -} - +//fun Element.displayObjectTree( +// obj: VisualObject, +// clickCallback: (Name) -> Unit = {} +//) { +// clear() +// append { +// card("Object tree") { +// subTree(Name.EMPTY, obj, clickCallback) +// } +// } +//} +// private fun TagConsumer.subTree( name: Name, obj: VisualObject, diff --git a/dataforge-vis-common/src/jsMain/kotlin/hep/dataforge/vis/js/editor/jsoneditor.kt b/dataforge-vis-common/src/jsMain/kotlin/hep/dataforge/vis/editor/jsoneditor.kt similarity index 99% rename from dataforge-vis-common/src/jsMain/kotlin/hep/dataforge/vis/js/editor/jsoneditor.kt rename to dataforge-vis-common/src/jsMain/kotlin/hep/dataforge/vis/editor/jsoneditor.kt index 8bfaf93a..800396cb 100644 --- a/dataforge-vis-common/src/jsMain/kotlin/hep/dataforge/vis/js/editor/jsoneditor.kt +++ b/dataforge-vis-common/src/jsMain/kotlin/hep/dataforge/vis/editor/jsoneditor.kt @@ -6,7 +6,7 @@ "EXTERNAL_DELEGATION" ) -package hep.dataforge.vis.js.editor +package hep.dataforge.vis.editor import org.w3c.dom.HTMLElement diff --git a/dataforge-vis-common/src/jsMain/kotlin/hep/dataforge/vis/editor/propertyEditor.kt b/dataforge-vis-common/src/jsMain/kotlin/hep/dataforge/vis/editor/propertyEditor.kt new file mode 100644 index 00000000..14891a13 --- /dev/null +++ b/dataforge-vis-common/src/jsMain/kotlin/hep/dataforge/vis/editor/propertyEditor.kt @@ -0,0 +1,107 @@ +package hep.dataforge.vis.editor + +import hep.dataforge.meta.Meta +import hep.dataforge.meta.MetaBuilder +import hep.dataforge.meta.descriptors.NodeDescriptor +import hep.dataforge.names.Name +import hep.dataforge.names.isEmpty +import hep.dataforge.vis.VisualObject +import org.w3c.dom.Element +import react.RBuilder +import react.ReactElement +import react.dom.li +import react.dom.nav +import react.dom.ol +import react.dom.render +import kotlin.collections.set + +////FIXME something rotten in JS-Meta converter +//fun Meta.toDynamic() = JSON.parse(toJson().toString()) +// +////TODO add node descriptor instead of configuring property selector +//fun Element.displayPropertyEditor( +// name: Name, +// item: VisualObject, +// propertySelector: (VisualObject) -> Meta = { it.config } +//) { +// clear() +// +// append { +// card("Properties") { +// if (!name.isEmpty()) { +// nav { +// attributes["aria-label"] = "breadcrumb" +// ol("breadcrumb") { +// name.tokens.forEach { token -> +// li("breadcrumb-item") { +// +token.toString() +// } +// } +// } +// } +// } +// val dMeta: dynamic = propertySelector(item).toDynamic() +// val options: JSONEditorOptions = jsObject { +// mode = "form" +// onChangeJSON = { item.config.update(DynamicMeta(it.asDynamic())) } +// } +// JSONEditor(div(), options, dMeta) +// } +// +// val styles = item.styles +// if (styles.isNotEmpty()) { +// card("Styles") { +// item.styles.forEach { style -> +// val styleMeta = item.findStyle(style) +// h4("container") { +style } +// if (styleMeta != null) { +// div("container").apply { +// val options: JSONEditorOptions = jsObject { +// mode = "view" +// } +// JSONEditor( +// this, +// options, +// styleMeta.toDynamic() +// ) +// } +// } +// } +// } +// } +// } +//} + +fun RBuilder.visualPropertyEditor( + path: Name, + item: VisualObject, + descriptor: NodeDescriptor? = item.descriptor, + title: String = "Properties", + default: MetaBuilder.() -> Unit = {} +): ReactElement = card(title) { + if (!path.isEmpty()) { + nav { + attrs { + attributes["aria-label"] = "breadcrumb" + } + ol("breadcrumb") { + path.tokens.forEach { token -> + li("breadcrumb-item") { + +token.toString() + } + } + } + } + } + configEditor(item.config, descriptor, Meta(default)) +} + +fun Element.visualPropertyEditor( + path: Name, + item: VisualObject, + descriptor: NodeDescriptor? = item.descriptor, + title: String = "Properties", + default: MetaBuilder.() -> Unit = {} +) = render(this) { + visualPropertyEditor(path, item, descriptor, title, default) +} \ No newline at end of file diff --git a/dataforge-vis-common/src/jsMain/kotlin/hep/dataforge/vis/js/editor/propertyEditor.kt b/dataforge-vis-common/src/jsMain/kotlin/hep/dataforge/vis/js/editor/propertyEditor.kt deleted file mode 100644 index 590c208f..00000000 --- a/dataforge-vis-common/src/jsMain/kotlin/hep/dataforge/vis/js/editor/propertyEditor.kt +++ /dev/null @@ -1,75 +0,0 @@ -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.update -import hep.dataforge.names.Name -import hep.dataforge.names.isEmpty -import hep.dataforge.vis.common.VisualObject -import hep.dataforge.vis.common.findStyle -import kotlinx.html.dom.append -import kotlinx.html.js.* -import org.w3c.dom.Element -import kotlin.collections.forEach -import kotlin.collections.isNotEmpty -import kotlin.collections.set -import kotlin.dom.clear - -//FIXME something rotten in JS-Meta converter -fun Meta.toDynamic() = JSON.parse(toJson().toString()) - -//TODO add node descriptor instead of configuring property selector -fun Element.displayPropertyEditor( - name: Name, - item: VisualObject, - propertySelector: (VisualObject) -> Meta = { it.config } -) { - clear() - - append { - card("Properties") { - if (!name.isEmpty()) { - nav { - attributes["aria-label"] = "breadcrumb" - ol("breadcrumb") { - name.tokens.forEach { token -> - li("breadcrumb-item") { - +token.toString() - } - } - } - } - } - val dMeta: dynamic = propertySelector(item).toDynamic() - val options: JSONEditorOptions = jsObject { - mode = "form" - onChangeJSON = { item.config.update(DynamicMeta(it.asDynamic())) } - } - JSONEditor(div(), options, dMeta) - } - - val styles = item.styles - if (styles.isNotEmpty()) { - card("Styles") { - item.styles.forEach { style -> - val styleMeta = item.findStyle(style) - h4("container") { +style } - if (styleMeta != null) { - div("container").apply { - val options: JSONEditorOptions = jsObject { - mode = "view" - } - JSONEditor( - this, - options, - styleMeta.toDynamic() - ) - } - } - } - } - } - } -} \ No newline at end of file diff --git a/dataforge-vis-common/src/jsMain/resources/css/common.css b/dataforge-vis-common/src/jsMain/resources/css/common.css index c5efcd40..4d1bac9d 100644 --- a/dataforge-vis-common/src/jsMain/resources/css/common.css +++ b/dataforge-vis-common/src/jsMain/resources/css/common.css @@ -21,3 +21,20 @@ ul, .objTree-subtree { .objTree-caret-down::before { transform: rotate(90deg); } + +ul, .tree { + list-style-type: none; +} + +i, .tree-caret{ + display: inline-block; + margin-right: 6px; +} + +.rotate { + transform: rotate(90deg); +} + +.tree-label-inactive { + color: gray; +} diff --git a/dataforge-vis-common/src/jvmMain/kotlin/hep/dataforge/vis/fx/FXPlugin.kt b/dataforge-vis-common/src/jvmMain/kotlin/hep/dataforge/vis/FXPlugin.kt similarity index 95% rename from dataforge-vis-common/src/jvmMain/kotlin/hep/dataforge/vis/fx/FXPlugin.kt rename to dataforge-vis-common/src/jvmMain/kotlin/hep/dataforge/vis/FXPlugin.kt index ffe2ef64..ca5a7c24 100644 --- a/dataforge-vis-common/src/jvmMain/kotlin/hep/dataforge/vis/fx/FXPlugin.kt +++ b/dataforge-vis-common/src/jvmMain/kotlin/hep/dataforge/vis/FXPlugin.kt @@ -1,7 +1,6 @@ -package hep.dataforge.vis.fx +package hep.dataforge.vis import hep.dataforge.context.* -import hep.dataforge.meta.EmptyMeta import hep.dataforge.meta.Meta import hep.dataforge.meta.boolean import javafx.application.Application @@ -20,7 +19,7 @@ import kotlin.reflect.KClass /** * Plugin holding JavaFX application instance and its root stage */ -class FXPlugin(meta: Meta = EmptyMeta) : AbstractPlugin(meta) { +class FXPlugin(meta: Meta = Meta.EMPTY) : AbstractPlugin(meta) { override val tag: PluginTag get() = Companion.tag private val stages: ObservableSet = FXCollections.observableSet() @@ -96,7 +95,8 @@ class FXPlugin(meta: Meta = EmptyMeta) : AbstractPlugin(meta) { 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 = FXPlugin(meta) + override fun invoke(meta: Meta, context: Context): FXPlugin = + FXPlugin(meta) } } diff --git a/dataforge-vis-common/src/jvmMain/kotlin/hep/dataforge/vis/fx/editor/ColorValueChooser.kt b/dataforge-vis-common/src/jvmMain/kotlin/hep/dataforge/vis/editor/ColorValueChooser.kt similarity index 97% rename from dataforge-vis-common/src/jvmMain/kotlin/hep/dataforge/vis/fx/editor/ColorValueChooser.kt rename to dataforge-vis-common/src/jvmMain/kotlin/hep/dataforge/vis/editor/ColorValueChooser.kt index 0dac4f8d..b130dc21 100644 --- a/dataforge-vis-common/src/jvmMain/kotlin/hep/dataforge/vis/fx/editor/ColorValueChooser.kt +++ b/dataforge-vis-common/src/jvmMain/kotlin/hep/dataforge/vis/editor/ColorValueChooser.kt @@ -1,4 +1,4 @@ -package hep.dataforge.vis.fx.editor +package hep.dataforge.vis.editor import hep.dataforge.meta.Meta import hep.dataforge.names.Name diff --git a/dataforge-vis-common/src/jvmMain/kotlin/hep/dataforge/vis/fx/editor/ComboBoxValueChooser.kt b/dataforge-vis-common/src/jvmMain/kotlin/hep/dataforge/vis/editor/ComboBoxValueChooser.kt similarity index 98% rename from dataforge-vis-common/src/jvmMain/kotlin/hep/dataforge/vis/fx/editor/ComboBoxValueChooser.kt rename to dataforge-vis-common/src/jvmMain/kotlin/hep/dataforge/vis/editor/ComboBoxValueChooser.kt index a3643099..3b7bdc33 100644 --- a/dataforge-vis-common/src/jvmMain/kotlin/hep/dataforge/vis/fx/editor/ComboBoxValueChooser.kt +++ b/dataforge-vis-common/src/jvmMain/kotlin/hep/dataforge/vis/editor/ComboBoxValueChooser.kt @@ -3,7 +3,7 @@ * To change this template file, choose Tools | Templates * and open the template in the editor. */ -package hep.dataforge.vis.fx.editor +package hep.dataforge.vis.editor import hep.dataforge.meta.Meta import hep.dataforge.meta.get diff --git a/dataforge-vis-common/src/jvmMain/kotlin/hep/dataforge/vis/fx/editor/ConfigEditor.kt b/dataforge-vis-common/src/jvmMain/kotlin/hep/dataforge/vis/editor/ConfigEditor.kt similarity index 95% rename from dataforge-vis-common/src/jvmMain/kotlin/hep/dataforge/vis/fx/editor/ConfigEditor.kt rename to dataforge-vis-common/src/jvmMain/kotlin/hep/dataforge/vis/editor/ConfigEditor.kt index 93af2df4..0b86456a 100644 --- a/dataforge-vis-common/src/jvmMain/kotlin/hep/dataforge/vis/fx/editor/ConfigEditor.kt +++ b/dataforge-vis-common/src/jvmMain/kotlin/hep/dataforge/vis/editor/ConfigEditor.kt @@ -3,15 +3,15 @@ * To change this template file, choose Tools | Templates * and open the template in the editor. */ -package hep.dataforge.vis.fx.editor +package hep.dataforge.vis.editor import de.jensd.fx.glyphs.fontawesome.FontAwesomeIcon import de.jensd.fx.glyphs.fontawesome.FontAwesomeIconView import hep.dataforge.context.Global -import hep.dataforge.descriptors.NodeDescriptor import hep.dataforge.meta.Config +import hep.dataforge.meta.descriptors.NodeDescriptor import hep.dataforge.names.NameToken -import hep.dataforge.vis.fx.dfIconView +import hep.dataforge.vis.dfIconView import javafx.scene.Node import javafx.scene.control.* import javafx.scene.control.cell.TextFieldTreeTableCell @@ -128,7 +128,11 @@ class ConfigEditor( when (item) { is FXMetaValue -> { text = null - val chooser = ValueChooser.build(Global, item.valueProperty, item.descriptor) { + val chooser = ValueChooser.build( + Global, + item.valueProperty, + item.descriptor + ) { item.set(it) } graphic = chooser.node diff --git a/dataforge-vis-common/src/jvmMain/kotlin/hep/dataforge/vis/fx/editor/FXMeta.kt b/dataforge-vis-common/src/jvmMain/kotlin/hep/dataforge/vis/editor/FXMeta.kt similarity index 95% rename from dataforge-vis-common/src/jvmMain/kotlin/hep/dataforge/vis/fx/editor/FXMeta.kt rename to dataforge-vis-common/src/jvmMain/kotlin/hep/dataforge/vis/editor/FXMeta.kt index 2eb14215..e4ed11a8 100644 --- a/dataforge-vis-common/src/jvmMain/kotlin/hep/dataforge/vis/fx/editor/FXMeta.kt +++ b/dataforge-vis-common/src/jvmMain/kotlin/hep/dataforge/vis/editor/FXMeta.kt @@ -1,9 +1,9 @@ -package hep.dataforge.vis.fx.editor +package hep.dataforge.vis.editor -import hep.dataforge.descriptors.ItemDescriptor -import hep.dataforge.descriptors.NodeDescriptor -import hep.dataforge.descriptors.ValueDescriptor 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 @@ -174,10 +174,10 @@ private fun > M.createEmptyNode(token: NameToken, append: Boo val name = token.asName() val index = (getIndexed(name).keys.mapNotNull { it.toIntOrNull() }.max() ?: -1) + 1 val newName = name.withIndex(index.toString()) - set(newName, EmptyMeta) + set(newName, Meta.EMPTY) get(newName).node!! } else { - this.setNode(token.asName(), EmptyMeta) + this.setNode(token.asName(), Meta.EMPTY) //FIXME possible concurrency bug get(token).node!! } @@ -211,9 +211,9 @@ fun > FXMetaNode.addValue(key: String) { fun > FXMetaNode.addNode(key: String) { val parent = getOrCreateNode() if (descriptor?.multiple == true) { - parent.append(key, EmptyMeta) + parent.append(key, Meta.EMPTY) } else { - parent[key] = EmptyMeta + parent[key] = Meta.EMPTY } } diff --git a/dataforge-vis-common/src/jvmMain/kotlin/hep/dataforge/vis/fx/editor/MetaViewer.kt b/dataforge-vis-common/src/jvmMain/kotlin/hep/dataforge/vis/editor/MetaViewer.kt similarity index 91% rename from dataforge-vis-common/src/jvmMain/kotlin/hep/dataforge/vis/fx/editor/MetaViewer.kt rename to dataforge-vis-common/src/jvmMain/kotlin/hep/dataforge/vis/editor/MetaViewer.kt index 1120ebf4..c433aac6 100644 --- a/dataforge-vis-common/src/jvmMain/kotlin/hep/dataforge/vis/fx/editor/MetaViewer.kt +++ b/dataforge-vis-common/src/jvmMain/kotlin/hep/dataforge/vis/editor/MetaViewer.kt @@ -14,18 +14,23 @@ * limitations under the License. */ -package hep.dataforge.vis.fx.editor +package hep.dataforge.vis.editor import hep.dataforge.meta.Meta -import hep.dataforge.vis.fx.dfIconView +import hep.dataforge.vis.dfIconView import javafx.beans.property.SimpleStringProperty import javafx.scene.control.TreeItem import javafx.scene.control.TreeSortMode import javafx.scene.control.TreeTableView import tornadofx.* -class MetaViewer(val rootNode: FXMetaNode<*>, title: String = "Meta viewer") : Fragment(title, dfIconView) { - constructor(meta: Meta, title: String = "Meta viewer"): this(FXMeta.root(meta),title = title) +class MetaViewer(val rootNode: FXMetaNode<*>, title: String = "Meta viewer") : Fragment(title, + dfIconView +) { + constructor(meta: Meta, title: String = "Meta viewer"): this( + FXMeta.root( + meta + ),title = title) override val root = borderpane { center { diff --git a/dataforge-vis-common/src/jvmMain/kotlin/hep/dataforge/vis/fx/editor/TextValueChooser.kt b/dataforge-vis-common/src/jvmMain/kotlin/hep/dataforge/vis/editor/TextValueChooser.kt similarity index 98% rename from dataforge-vis-common/src/jvmMain/kotlin/hep/dataforge/vis/fx/editor/TextValueChooser.kt rename to dataforge-vis-common/src/jvmMain/kotlin/hep/dataforge/vis/editor/TextValueChooser.kt index 92e59acf..c1f611fb 100644 --- a/dataforge-vis-common/src/jvmMain/kotlin/hep/dataforge/vis/fx/editor/TextValueChooser.kt +++ b/dataforge-vis-common/src/jvmMain/kotlin/hep/dataforge/vis/editor/TextValueChooser.kt @@ -3,7 +3,7 @@ * To change this template file, choose Tools | Templates * and open the template in the editor. */ -package hep.dataforge.vis.fx.editor +package hep.dataforge.vis.editor import hep.dataforge.meta.Meta import hep.dataforge.names.Name diff --git a/dataforge-vis-common/src/jvmMain/kotlin/hep/dataforge/vis/fx/editor/ValueCallback.kt b/dataforge-vis-common/src/jvmMain/kotlin/hep/dataforge/vis/editor/ValueCallback.kt similarity index 94% rename from dataforge-vis-common/src/jvmMain/kotlin/hep/dataforge/vis/fx/editor/ValueCallback.kt rename to dataforge-vis-common/src/jvmMain/kotlin/hep/dataforge/vis/editor/ValueCallback.kt index bf7cdb7b..7989eaed 100644 --- a/dataforge-vis-common/src/jvmMain/kotlin/hep/dataforge/vis/fx/editor/ValueCallback.kt +++ b/dataforge-vis-common/src/jvmMain/kotlin/hep/dataforge/vis/editor/ValueCallback.kt @@ -3,7 +3,7 @@ * To change this template file, choose Tools | Templates * and open the template in the editor. */ -package hep.dataforge.vis.fx.editor +package hep.dataforge.vis.editor import hep.dataforge.values.Value diff --git a/dataforge-vis-common/src/jvmMain/kotlin/hep/dataforge/vis/fx/editor/ValueChooser.kt b/dataforge-vis-common/src/jvmMain/kotlin/hep/dataforge/vis/editor/ValueChooser.kt similarity index 91% rename from dataforge-vis-common/src/jvmMain/kotlin/hep/dataforge/vis/fx/editor/ValueChooser.kt rename to dataforge-vis-common/src/jvmMain/kotlin/hep/dataforge/vis/editor/ValueChooser.kt index f8946a4a..56794fcb 100644 --- a/dataforge-vis-common/src/jvmMain/kotlin/hep/dataforge/vis/fx/editor/ValueChooser.kt +++ b/dataforge-vis-common/src/jvmMain/kotlin/hep/dataforge/vis/editor/ValueChooser.kt @@ -3,20 +3,19 @@ * To change this template file, choose Tools | Templates * and open the template in the editor. */ -package hep.dataforge.vis.fx.editor +package hep.dataforge.vis.editor import hep.dataforge.context.Context import hep.dataforge.context.Named -import hep.dataforge.descriptors.ValueDescriptor -import hep.dataforge.meta.EmptyMeta import hep.dataforge.meta.Meta +import hep.dataforge.meta.descriptors.ValueDescriptor import hep.dataforge.names.toName import hep.dataforge.provider.Type import hep.dataforge.provider.provideByType import hep.dataforge.values.Null import hep.dataforge.values.Value -import hep.dataforge.vis.common.widget -import hep.dataforge.vis.common.widgetType +import hep.dataforge.vis.widget +import hep.dataforge.vis.widgetType import javafx.beans.property.ObjectProperty import javafx.beans.value.ObservableValue import javafx.scene.Node @@ -66,7 +65,7 @@ interface ValueChooser { @Type("hep.dataforge.vis.fx.valueChooserFactory") interface Factory : Named { - operator fun invoke(meta: Meta = EmptyMeta): ValueChooser + operator fun invoke(meta: Meta = Meta.EMPTY): ValueChooser } companion object { @@ -108,8 +107,7 @@ 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) diff --git a/dataforge-vis-common/src/jvmMain/kotlin/hep/dataforge/vis/fx/editor/ValueChooserBase.kt b/dataforge-vis-common/src/jvmMain/kotlin/hep/dataforge/vis/editor/ValueChooserBase.kt similarity index 95% rename from dataforge-vis-common/src/jvmMain/kotlin/hep/dataforge/vis/fx/editor/ValueChooserBase.kt rename to dataforge-vis-common/src/jvmMain/kotlin/hep/dataforge/vis/editor/ValueChooserBase.kt index 7cbbcc1f..9c415a43 100644 --- a/dataforge-vis-common/src/jvmMain/kotlin/hep/dataforge/vis/fx/editor/ValueChooserBase.kt +++ b/dataforge-vis-common/src/jvmMain/kotlin/hep/dataforge/vis/editor/ValueChooserBase.kt @@ -3,9 +3,9 @@ * To change this template file, choose Tools | Templates * and open the template in the editor. */ -package hep.dataforge.vis.fx.editor +package hep.dataforge.vis.editor -import hep.dataforge.descriptors.ValueDescriptor +import hep.dataforge.meta.descriptors.ValueDescriptor import hep.dataforge.values.Null import hep.dataforge.values.Value import javafx.beans.property.SimpleObjectProperty diff --git a/dataforge-vis-common/src/jvmMain/kotlin/hep/dataforge/vis/fx/editor/VisualObjectEditorFragment.kt b/dataforge-vis-common/src/jvmMain/kotlin/hep/dataforge/vis/editor/VisualObjectEditorFragment.kt similarity index 93% rename from dataforge-vis-common/src/jvmMain/kotlin/hep/dataforge/vis/fx/editor/VisualObjectEditorFragment.kt rename to dataforge-vis-common/src/jvmMain/kotlin/hep/dataforge/vis/editor/VisualObjectEditorFragment.kt index fd52d64c..43cdf21f 100644 --- a/dataforge-vis-common/src/jvmMain/kotlin/hep/dataforge/vis/fx/editor/VisualObjectEditorFragment.kt +++ b/dataforge-vis-common/src/jvmMain/kotlin/hep/dataforge/vis/editor/VisualObjectEditorFragment.kt @@ -1,11 +1,11 @@ -package hep.dataforge.vis.fx.editor +package hep.dataforge.vis.editor -import hep.dataforge.descriptors.NodeDescriptor import hep.dataforge.meta.Config import hep.dataforge.meta.Meta +import hep.dataforge.meta.descriptors.NodeDescriptor import hep.dataforge.meta.update -import hep.dataforge.vis.common.VisualObject -import hep.dataforge.vis.common.findStyle +import hep.dataforge.vis.VisualObject +import hep.dataforge.vis.findStyle import javafx.beans.binding.Binding import javafx.beans.property.SimpleObjectProperty import javafx.scene.Node diff --git a/dataforge-vis-common/src/jvmMain/kotlin/hep/dataforge/vis/fx/editor/VisualObjectTreeFragment.kt b/dataforge-vis-common/src/jvmMain/kotlin/hep/dataforge/vis/editor/VisualObjectTreeFragment.kt similarity index 93% rename from dataforge-vis-common/src/jvmMain/kotlin/hep/dataforge/vis/fx/editor/VisualObjectTreeFragment.kt rename to dataforge-vis-common/src/jvmMain/kotlin/hep/dataforge/vis/editor/VisualObjectTreeFragment.kt index 4f27ef87..fad759b9 100644 --- a/dataforge-vis-common/src/jvmMain/kotlin/hep/dataforge/vis/fx/editor/VisualObjectTreeFragment.kt +++ b/dataforge-vis-common/src/jvmMain/kotlin/hep/dataforge/vis/editor/VisualObjectTreeFragment.kt @@ -1,7 +1,7 @@ -package hep.dataforge.vis.fx.editor +package hep.dataforge.vis.editor -import hep.dataforge.vis.common.VisualGroup -import hep.dataforge.vis.common.VisualObject +import hep.dataforge.vis.VisualGroup +import hep.dataforge.vis.VisualObject import javafx.beans.property.SimpleObjectProperty import javafx.scene.control.SelectionMode import javafx.scene.control.TreeItem diff --git a/dataforge-vis-common/src/jvmTest/kotlin/hep/dataforge/vis/fx/demo/MetaEditorDemo.kt b/dataforge-vis-common/src/jvmTest/kotlin/hep/dataforge/vis/demo/MetaEditorDemo.kt similarity index 60% rename from dataforge-vis-common/src/jvmTest/kotlin/hep/dataforge/vis/fx/demo/MetaEditorDemo.kt rename to dataforge-vis-common/src/jvmTest/kotlin/hep/dataforge/vis/demo/MetaEditorDemo.kt index 09ec35fc..0c4060f1 100644 --- a/dataforge-vis-common/src/jvmTest/kotlin/hep/dataforge/vis/fx/demo/MetaEditorDemo.kt +++ b/dataforge-vis-common/src/jvmTest/kotlin/hep/dataforge/vis/demo/MetaEditorDemo.kt @@ -1,12 +1,12 @@ -package hep.dataforge.vis.fx.demo +package hep.dataforge.vis.demo -import hep.dataforge.descriptors.NodeDescriptor -import hep.dataforge.meta.buildMeta -import hep.dataforge.meta.toConfig +import hep.dataforge.meta.Meta +import hep.dataforge.meta.asConfig +import hep.dataforge.meta.descriptors.NodeDescriptor import hep.dataforge.values.ValueType -import hep.dataforge.vis.fx.editor.ConfigEditor -import hep.dataforge.vis.fx.editor.FXMeta -import hep.dataforge.vis.fx.editor.MetaViewer +import hep.dataforge.vis.editor.ConfigEditor +import hep.dataforge.vis.editor.FXMeta +import hep.dataforge.vis.editor.MetaViewer import javafx.geometry.Orientation import tornadofx.* @@ -15,7 +15,7 @@ class MetaEditorDemoApp : App(MetaEditorDemo::class) class MetaEditorDemo : View("Meta editor demo") { - val meta = buildMeta { + val meta = Meta { "aNode" put { "innerNode" put { "innerValue" put true @@ -23,33 +23,35 @@ class MetaEditorDemo : View("Meta editor demo") { "b" put 223 "c" put "StringValue" } - }.toConfig() + }.asConfig() val descriptor = NodeDescriptor { - node("aNode") { + defineNode("aNode") { info = "A root demo node" - value("b") { + defineValue("b") { info = "b number value" type(ValueType.NUMBER) } - node("otherNode") { - value("otherValue") { + defineNode("otherNode") { + defineValue("otherValue") { type(ValueType.BOOLEAN) default(false) info = "default value" } } } - value("multiple"){ + defineValue("multiple") { info = "A sns value" multiple = true } } - private val rootNode = FXMeta.root(meta,descriptor) + private val rootNode = FXMeta.root(meta, descriptor) override val root = - splitpane(Orientation.HORIZONTAL, MetaViewer(rootNode).root, ConfigEditor(rootNode).root) + splitpane(Orientation.HORIZONTAL, MetaViewer(rootNode).root, ConfigEditor( + rootNode + ).root) } fun main() { diff --git a/dataforge-vis-spatial-gdml/build.gradle.kts b/dataforge-vis-spatial-gdml/build.gradle.kts index c13e2e3f..a2a0bce8 100644 --- a/dataforge-vis-spatial-gdml/build.gradle.kts +++ b/dataforge-vis-spatial-gdml/build.gradle.kts @@ -7,7 +7,7 @@ kotlin { val commonMain by getting { dependencies { api(project(":dataforge-vis-spatial")) - api("scientifik:gdml:0.1.6") + api("scientifik:gdml:0.1.7") } } } diff --git a/dataforge-vis-spatial-gdml/src/commonMain/kotlin/hep/dataforge/vis/spatial/gdml/GDMLTransformer.kt b/dataforge-vis-spatial-gdml/src/commonMain/kotlin/hep/dataforge/vis/spatial/gdml/GDMLTransformer.kt index 9d664aff..1ee32597 100644 --- a/dataforge-vis-spatial-gdml/src/commonMain/kotlin/hep/dataforge/vis/spatial/gdml/GDMLTransformer.kt +++ b/dataforge-vis-spatial-gdml/src/commonMain/kotlin/hep/dataforge/vis/spatial/gdml/GDMLTransformer.kt @@ -2,12 +2,12 @@ package hep.dataforge.vis.spatial.gdml import hep.dataforge.meta.Meta import hep.dataforge.meta.MetaBuilder -import hep.dataforge.meta.buildMeta import hep.dataforge.names.Name +import hep.dataforge.names.asName import hep.dataforge.names.toName -import hep.dataforge.vis.common.useStyle import hep.dataforge.vis.spatial.* import hep.dataforge.vis.spatial.Material3D.Companion.MATERIAL_COLOR_KEY +import hep.dataforge.vis.useStyle import scientifik.gdml.* import kotlin.random.Random @@ -44,7 +44,7 @@ class GDMLTransformer(val root: GDML) { fun VisualObject3D.useStyle(name: String, builder: MetaBuilder.() -> Unit) { styleCache.getOrPut(name.toName()) { - buildMeta(builder) + Meta(builder) } useStyle(name) } @@ -69,7 +69,13 @@ class GDMLTransformer(val root: GDML) { var onFinish: GDMLTransformer.() -> Unit = {} internal fun finalize(final: VisualGroup3D): VisualGroup3D { - final.prototypes = proto + //final.prototypes = proto + final.prototypes { + proto.children.forEach { (token, item) -> + item.parent = null + set(token.asName(), item) + } + } styleCache.forEach { final.styleSheet { define(it.key.toString(), it.value) diff --git a/dataforge-vis-spatial-gdml/src/commonMain/kotlin/hep/dataforge/vis/spatial/gdml/visualGDML.kt b/dataforge-vis-spatial-gdml/src/commonMain/kotlin/hep/dataforge/vis/spatial/gdml/visualGDML.kt index 1f72a899..9f3bb093 100644 --- a/dataforge-vis-spatial-gdml/src/commonMain/kotlin/hep/dataforge/vis/spatial/gdml/visualGDML.kt +++ b/dataforge-vis-spatial-gdml/src/commonMain/kotlin/hep/dataforge/vis/spatial/gdml/visualGDML.kt @@ -4,8 +4,8 @@ package hep.dataforge.vis.spatial.gdml import hep.dataforge.names.Name import hep.dataforge.names.asName import hep.dataforge.names.plus -import hep.dataforge.vis.common.get -import hep.dataforge.vis.common.set +import hep.dataforge.vis.get +import hep.dataforge.vis.set import hep.dataforge.vis.spatial.* import hep.dataforge.vis.spatial.World.ONE import hep.dataforge.vis.spatial.World.ZERO diff --git a/dataforge-vis-spatial-gdml/src/jvmTest/kotlin/hep/dataforge/vis/spatial/gdml/TestConvertor.kt b/dataforge-vis-spatial-gdml/src/jvmTest/kotlin/hep/dataforge/vis/spatial/gdml/TestConvertor.kt index f9cad99c..8d62967b 100644 --- a/dataforge-vis-spatial-gdml/src/jvmTest/kotlin/hep/dataforge/vis/spatial/gdml/TestConvertor.kt +++ b/dataforge-vis-spatial-gdml/src/jvmTest/kotlin/hep/dataforge/vis/spatial/gdml/TestConvertor.kt @@ -1,43 +1,29 @@ package hep.dataforge.vis.spatial.gdml +import hep.dataforge.vis.spatial.stringify import nl.adaptivity.xmlutil.StAXReader -import org.junit.Test +import org.junit.jupiter.api.Test import scientifik.gdml.GDML -import java.io.File -import java.net.URL -import kotlin.test.Ignore class TestConvertor { @Test - @Ignore fun testBMNGeometry() { - val url = URL("https://drive.google.com/open?id=1w5e7fILMN83JGgB8WANJUYm8OW2s0WVO") - val file = File("D:\\Work\\Projects\\gdml.kt\\gdml-source\\BM@N.gdml") - val stream = if (file.exists()) { - file.inputStream() - } else { - url.openStream() - } - - val xmlReader = StAXReader(stream, "UTF-8") - val xml = GDML.format.parse(GDML.serializer(), xmlReader) - xml.toVisual() - } - - @Test - @Ignore - fun testCubes() { - val file = File("D:\\Work\\Projects\\gdml.kt\\gdml-source\\cubes.gdml ") - val stream = if (file.exists()) { - file.inputStream() - } else { - return - } + 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.toVisual() - println(visual) + println(visual.stringify()) + } + + @Test + fun testCubes() { + val stream = javaClass.getResourceAsStream("/gdml/cubes.gdml") + + val xmlReader = StAXReader(stream, "UTF-8") + val xml = GDML.format.parse(GDML.serializer(), xmlReader) + val visual = xml.toVisual() + // println(visual) } } \ No newline at end of file diff --git a/dataforge-vis-spatial-gdml/src/jvmTest/resources/gdml/BM@N.gdml b/dataforge-vis-spatial-gdml/src/jvmTest/resources/gdml/BM@N.gdml new file mode 100644 index 00000000..7336adf4 --- /dev/null +++ b/dataforge-vis-spatial-gdml/src/jvmTest/resources/gdml/BM@N.gdml @@ -0,0 +1,5601 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + + + + + + + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
+ + + + + + + +
+
+ + + + + + + + + + + + + +
+
+ + + + + + + + + + + + +
+
+ + + + + + + + +
+
+ + + + + + + +
+
+ + + + + + + + + + + + + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
+ + + + + + + +
+
+ + + + + + + + + + + + + +
+
+ + + + + + + + + + + + +
+
+ + + + + + + + +
+
+ + + + + + + +
+
+ + + + + + + + + + + + + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dataforge-vis-spatial-gdml/src/jvmTest/resources/gdml/cubes.gdml b/dataforge-vis-spatial-gdml/src/jvmTest/resources/gdml/cubes.gdml new file mode 100644 index 00000000..bd656261 --- /dev/null +++ b/dataforge-vis-spatial-gdml/src/jvmTest/resources/gdml/cubes.gdml @@ -0,0 +1,254 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/dataforge-vis-spatial/build.gradle.kts b/dataforge-vis-spatial/build.gradle.kts index f587d39d..b6b050a5 100644 --- a/dataforge-vis-spatial/build.gradle.kts +++ b/dataforge-vis-spatial/build.gradle.kts @@ -1,17 +1,12 @@ -import org.openjfx.gradle.JavaFXOptions -import scientifik.useSerialization +import scientifik.serialization plugins { id("scientifik.mpp") - id("org.openjfx.javafxplugin") } -useSerialization() +serialization() kotlin { - jvm { - withJava() - } sourceSets { commonMain { dependencies { @@ -32,14 +27,9 @@ kotlin { jsMain { dependencies { // api(project(":wrappers")) - implementation(npm("three", "0.106.2")) - implementation(npm("@hi-level/three-csg", "1.0.6")) + implementation(npm("three", "0.114.0")) + implementation(npm("three-csg-ts", "1.0.1")) } } } } - -configure { - modules("javafx.controls") -} - diff --git a/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/Box.kt b/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/Box.kt index c2010a0f..58b10756 100644 --- a/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/Box.kt +++ b/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/Box.kt @@ -2,15 +2,11 @@ package hep.dataforge.vis.spatial import hep.dataforge.context.Context -import hep.dataforge.io.serialization.ConfigSerializer import hep.dataforge.meta.Config import hep.dataforge.meta.Meta import hep.dataforge.meta.float import hep.dataforge.meta.get -import hep.dataforge.vis.common.AbstractVisualObject -import hep.dataforge.vis.common.VisualFactory -import hep.dataforge.vis.common.VisualObject -import hep.dataforge.vis.common.set +import hep.dataforge.vis.* import hep.dataforge.vis.spatial.Box.Companion.TYPE_NAME import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable @@ -29,7 +25,6 @@ class Box( override var rotation: Point3D? = null override var scale: Point3D? = null - @Serializable(ConfigSerializer::class) override var properties: Config? = null //TODO add helper for color configuration @@ -69,7 +64,7 @@ class Box( } } -inline fun VisualGroup3D.box( +inline fun MutableVisualGroup.box( xSize: Number, ySize: Number, zSize: Number, diff --git a/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/Composite.kt b/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/Composite.kt index a7b3c774..a41cb12c 100644 --- a/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/Composite.kt +++ b/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/Composite.kt @@ -2,11 +2,10 @@ package hep.dataforge.vis.spatial -import hep.dataforge.io.serialization.ConfigSerializer import hep.dataforge.meta.Config import hep.dataforge.meta.update -import hep.dataforge.vis.common.AbstractVisualObject -import hep.dataforge.vis.common.set +import hep.dataforge.names.NameToken +import hep.dataforge.vis.* import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable import kotlinx.serialization.UseSerializers @@ -23,7 +22,7 @@ class Composite( val compositeType: CompositeType, val first: VisualObject3D, val second: VisualObject3D -) : AbstractVisualObject(), VisualObject3D { +) : AbstractVisualObject(), VisualObject3D, VisualGroup { init { first.parent = this @@ -34,11 +33,16 @@ class Composite( override var rotation: Point3D? = null override var scale: Point3D? = null - @Serializable(ConfigSerializer::class) override var properties: Config? = null + + override val children: Map + get() = mapOf(NameToken("first") to first, NameToken("second") to second) + + override val styleSheet: StyleSheet? + get() = null } -inline fun VisualGroup3D.composite( +inline fun MutableVisualGroup.composite( type: CompositeType, name: String = "", builder: VisualGroup3D.() -> Unit @@ -50,24 +54,24 @@ inline fun VisualGroup3D.composite( it.config.update(group.config) //it.material = group.material - if(group.position!=null) { + if (group.position != null) { it.position = group.position } - if(group.rotation!=null) { + if (group.rotation != null) { it.rotation = group.rotation } - if(group.scale!=null) { + if (group.scale != null) { it.scale = group.scale } set(name, it) } } -fun VisualGroup3D.union(name: String = "", builder: VisualGroup3D.() -> Unit) = +inline fun MutableVisualGroup.union(name: String = "", builder: VisualGroup3D.() -> Unit) = composite(CompositeType.UNION, name, builder = builder) -fun VisualGroup3D.subtract(name: String = "", builder: VisualGroup3D.() -> Unit) = +inline fun MutableVisualGroup.subtract(name: String = "", builder: VisualGroup3D.() -> Unit) = composite(CompositeType.SUBTRACT, name, builder = builder) -fun VisualGroup3D.intersect(name: String = "", builder: VisualGroup3D.() -> Unit) = +inline fun MutableVisualGroup.intersect(name: String = "", builder: VisualGroup3D.() -> Unit) = composite(CompositeType.INTERSECT, name, builder = builder) \ No newline at end of file diff --git a/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/ConeSegment.kt b/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/ConeSegment.kt index f373a8de..6ed2cbdf 100644 --- a/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/ConeSegment.kt +++ b/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/ConeSegment.kt @@ -2,10 +2,10 @@ package hep.dataforge.vis.spatial -import hep.dataforge.io.serialization.ConfigSerializer import hep.dataforge.meta.Config -import hep.dataforge.vis.common.AbstractVisualObject -import hep.dataforge.vis.common.set +import hep.dataforge.vis.AbstractVisualObject +import hep.dataforge.vis.MutableVisualGroup +import hep.dataforge.vis.set import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable import kotlinx.serialization.UseSerializers @@ -25,7 +25,6 @@ class ConeSegment( var angle: Float = PI2 ) : AbstractVisualObject(), VisualObject3D, Shape { - @Serializable(ConfigSerializer::class) override var properties: Config? = null override var position: Point3D? = null @@ -76,7 +75,7 @@ class ConeSegment( } -inline fun VisualGroup3D.cylinder( +inline fun MutableVisualGroup.cylinder( r: Number, height: Number, name: String = "", @@ -88,7 +87,7 @@ inline fun VisualGroup3D.cylinder( ).apply(block).also { set(name, it) } -inline fun VisualGroup3D.cone( +inline fun MutableVisualGroup.cone( bottomRadius: Number, height: Number, upperRadius: Number = 0.0, diff --git a/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/Convex.kt b/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/Convex.kt index e4168ed6..c75c2e4c 100644 --- a/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/Convex.kt +++ b/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/Convex.kt @@ -2,10 +2,10 @@ package hep.dataforge.vis.spatial -import hep.dataforge.io.serialization.ConfigSerializer import hep.dataforge.meta.Config -import hep.dataforge.vis.common.AbstractVisualObject -import hep.dataforge.vis.common.set +import hep.dataforge.vis.AbstractVisualObject +import hep.dataforge.vis.MutableVisualGroup +import hep.dataforge.vis.set import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable import kotlinx.serialization.UseSerializers @@ -14,7 +14,6 @@ import kotlinx.serialization.UseSerializers @SerialName("3d.convex") class Convex(val points: List) : AbstractVisualObject(), VisualObject3D { - @Serializable(ConfigSerializer::class) override var properties: Config? = null override var position: Point3D? = null @@ -26,7 +25,7 @@ class Convex(val points: List) : AbstractVisualObject(), VisualObject3D } } -inline fun VisualGroup3D.convex(name: String = "", action: ConvexBuilder.() -> Unit = {}) = +inline fun MutableVisualGroup.convex(name: String = "", action: ConvexBuilder.() -> Unit = {}) = ConvexBuilder().apply(action).build().also { set(name, it) } class ConvexBuilder { diff --git a/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/Extruded.kt b/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/Extruded.kt index ae81eace..46cd2a53 100644 --- a/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/Extruded.kt +++ b/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/Extruded.kt @@ -1,10 +1,10 @@ @file:UseSerializers(Point2DSerializer::class, Point3DSerializer::class) package hep.dataforge.vis.spatial -import hep.dataforge.io.serialization.ConfigSerializer import hep.dataforge.meta.Config -import hep.dataforge.vis.common.AbstractVisualObject -import hep.dataforge.vis.common.set +import hep.dataforge.vis.AbstractVisualObject +import hep.dataforge.vis.MutableVisualGroup +import hep.dataforge.vis.set import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable import kotlinx.serialization.UseSerializers @@ -45,7 +45,6 @@ class Extruded( var layers: MutableList = ArrayList() ) : AbstractVisualObject(), VisualObject3D, Shape { - @Serializable(ConfigSerializer::class) override var properties: Config? = null override var position: Point3D? = null @@ -113,5 +112,5 @@ class Extruded( } } -fun VisualGroup3D.extrude(name: String = "", action: Extruded.() -> Unit = {}) = +fun MutableVisualGroup.extrude(name: String = "", action: Extruded.() -> Unit = {}) = Extruded().apply(action).also { set(name, it) } \ No newline at end of file diff --git a/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/GeometryBuilder.kt b/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/GeometryBuilder.kt index efc623d9..f189a007 100644 --- a/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/GeometryBuilder.kt +++ b/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/GeometryBuilder.kt @@ -1,6 +1,5 @@ package hep.dataforge.vis.spatial -import hep.dataforge.meta.EmptyMeta import hep.dataforge.meta.Meta /** @@ -14,7 +13,7 @@ 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 = EmptyMeta) + fun face(vertex1: Point3D, vertex2: Point3D, vertex3: Point3D, normal: Point3D? = null, meta: Meta = Meta.EMPTY) fun build(): T } @@ -25,7 +24,7 @@ fun GeometryBuilder<*>.face4( vertex3: Point3D, vertex4: Point3D, normal: Point3D? = null, - meta: Meta = EmptyMeta + meta: Meta = Meta.EMPTY ) { face(vertex1, vertex2, vertex3, normal, meta) face(vertex1, vertex3, vertex4, normal, meta) diff --git a/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/Label3D.kt b/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/Label3D.kt index 906b03de..ac9184d3 100644 --- a/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/Label3D.kt +++ b/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/Label3D.kt @@ -2,19 +2,17 @@ package hep.dataforge.vis.spatial -import hep.dataforge.io.serialization.ConfigSerializer import hep.dataforge.meta.Config -import hep.dataforge.vis.common.AbstractVisualObject -import hep.dataforge.vis.common.set +import hep.dataforge.vis.AbstractVisualObject +import hep.dataforge.vis.MutableVisualGroup +import hep.dataforge.vis.set import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable import kotlinx.serialization.UseSerializers @Serializable @SerialName("3d.label") -class Label3D(var text: String, var fontSize: Double, var fontFamily: String) : AbstractVisualObject(), - VisualObject3D { - @Serializable(ConfigSerializer::class) +class Label3D(var text: String, var fontSize: Double, var fontFamily: String) : AbstractVisualObject(), VisualObject3D { override var properties: Config? = null override var position: Point3D? = null @@ -23,7 +21,7 @@ class Label3D(var text: String, var fontSize: Double, var fontFamily: String) : } -fun VisualGroup3D.label( +fun MutableVisualGroup.label( text: String, fontSize: Number = 20, fontFamily: String = "Arial", diff --git a/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/Material3D.kt b/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/Material3D.kt index f489c62a..5e16fadf 100644 --- a/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/Material3D.kt +++ b/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/Material3D.kt @@ -1,16 +1,17 @@ package hep.dataforge.vis.spatial -import hep.dataforge.descriptors.NodeDescriptor import hep.dataforge.meta.* +import hep.dataforge.meta.descriptors.NodeDescriptor import hep.dataforge.names.asName import hep.dataforge.names.plus import hep.dataforge.values.ValueType -import hep.dataforge.vis.common.Colors +import hep.dataforge.values.asValue +import hep.dataforge.vis.Colors import hep.dataforge.vis.spatial.Material3D.Companion.MATERIAL_COLOR_KEY import hep.dataforge.vis.spatial.Material3D.Companion.MATERIAL_KEY import hep.dataforge.vis.spatial.Material3D.Companion.MATERIAL_OPACITY_KEY -class Material3D(override val config: Config) : Specific { +class Material3D : Scheme() { /** * Primary web-color for the material @@ -32,8 +33,7 @@ class Material3D(override val config: Config) : Specific { */ var wireframe by boolean(false, WIREFRAME_KEY) - companion object : Specification { - override fun wrap(config: Config): Material3D = Material3D(config) + companion object : SchemeSpec(::Material3D) { val MATERIAL_KEY = "material".asName() internal val COLOR_KEY = "color".asName() @@ -44,23 +44,26 @@ class Material3D(override val config: Config) : Specific { internal val WIREFRAME_KEY = "wireframe".asName() val MATERIAL_WIREFRAME_KEY = MATERIAL_KEY + WIREFRAME_KEY - val descriptor = NodeDescriptor { - value(VisualObject3D.VISIBLE_KEY) { - type(ValueType.BOOLEAN) - default(true) - } - node(MATERIAL_KEY) { - value(COLOR_KEY) { - type(ValueType.STRING, ValueType.NUMBER) - default("#ffffff") - } - value(OPACITY_KEY) { - type(ValueType.NUMBER) - default(1.0) - } - value(WIREFRAME_KEY) { + val descriptor by lazy { + //must be lazy to avoid initialization bug + NodeDescriptor { + defineValue(VisualObject3D.VISIBLE_KEY) { type(ValueType.BOOLEAN) - default(false) + default(true) + } + defineNode(MATERIAL_KEY) { + defineValue(COLOR_KEY) { + type(ValueType.STRING, ValueType.NUMBER) + default("#ffffff") + } + defineValue(OPACITY_KEY) { + type(ValueType.NUMBER) + default(1.0) + } + defineValue(WIREFRAME_KEY) { + type(ValueType.BOOLEAN) + default(false) + } } } } @@ -71,14 +74,14 @@ class Material3D(override val config: Config) : Specific { * Set color as web-color */ fun VisualObject3D.color(webColor: String) { - setProperty(MATERIAL_COLOR_KEY, webColor) + setProperty(MATERIAL_COLOR_KEY, webColor.asValue()) } /** * Set color as integer */ fun VisualObject3D.color(rgb: Int) { - setProperty(MATERIAL_COLOR_KEY, rgb) + setProperty(MATERIAL_COLOR_KEY, rgb.asValue()) } fun VisualObject3D.color(r: UByte, g: UByte, b: UByte) = setProperty( @@ -92,7 +95,7 @@ fun VisualObject3D.color(r: UByte, g: UByte, b: UByte) = setProperty( var VisualObject3D.color: String? get() = getProperty(MATERIAL_COLOR_KEY)?.let { Colors.fromMeta(it) } set(value) { - setProperty(MATERIAL_COLOR_KEY, value) + setProperty(MATERIAL_COLOR_KEY, value?.asValue()) } val VisualObject3D.material: Material3D? @@ -110,5 +113,5 @@ fun VisualObject3D.material(builder: Material3D.() -> Unit) { var VisualObject3D.opacity: Double? get() = getProperty(MATERIAL_OPACITY_KEY).double set(value) { - setProperty(MATERIAL_OPACITY_KEY, value) + setProperty(MATERIAL_OPACITY_KEY, value?.asValue()) } \ No newline at end of file diff --git a/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/PolyLine.kt b/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/PolyLine.kt index 24f5a3b9..220b0ada 100644 --- a/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/PolyLine.kt +++ b/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/PolyLine.kt @@ -2,13 +2,13 @@ package hep.dataforge.vis.spatial -import hep.dataforge.io.serialization.ConfigSerializer import hep.dataforge.meta.Config import hep.dataforge.meta.number import hep.dataforge.names.asName import hep.dataforge.names.plus -import hep.dataforge.vis.common.AbstractVisualObject -import hep.dataforge.vis.common.set +import hep.dataforge.vis.AbstractVisualObject +import hep.dataforge.vis.MutableVisualGroup +import hep.dataforge.vis.set import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable import kotlinx.serialization.UseSerializers @@ -16,7 +16,6 @@ import kotlinx.serialization.UseSerializers @Serializable @SerialName("3d.line") class PolyLine(var points: List) : AbstractVisualObject(), VisualObject3D { - @Serializable(ConfigSerializer::class) override var properties: Config? = null override var position: Point3D? = null @@ -32,5 +31,5 @@ class PolyLine(var points: List) : AbstractVisualObject(), VisualObject } -fun VisualGroup3D.polyline(vararg points: Point3D, name: String = "", action: PolyLine.() -> Unit = {}) = +fun MutableVisualGroup.polyline(vararg points: Point3D, name: String = "", action: PolyLine.() -> Unit = {}) = PolyLine(points.toList()).apply(action).also { set(name, it) } \ No newline at end of file diff --git a/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/Proxy.kt b/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/Proxy.kt index 9b72e6d5..b60f8d42 100644 --- a/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/Proxy.kt +++ b/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/Proxy.kt @@ -1,18 +1,13 @@ -@file:UseSerializers(Point3DSerializer::class, NameSerializer::class, ConfigSerializer::class) +@file:UseSerializers(Point3DSerializer::class) package hep.dataforge.vis.spatial -import hep.dataforge.io.serialization.ConfigSerializer -import hep.dataforge.io.serialization.NameSerializer import hep.dataforge.meta.Config import hep.dataforge.meta.Laminate import hep.dataforge.meta.MetaItem import hep.dataforge.meta.get -import hep.dataforge.names.Name -import hep.dataforge.names.NameToken -import hep.dataforge.names.asName -import hep.dataforge.names.plus -import hep.dataforge.vis.common.* +import hep.dataforge.names.* +import hep.dataforge.vis.* import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable import kotlinx.serialization.Transient @@ -26,7 +21,9 @@ import kotlin.collections.set */ @Serializable @SerialName("3d.proxy") -class Proxy private constructor(val templateName: Name) : AbstractVisualObject(), VisualGroup, VisualObject3D { +class Proxy private constructor( + val templateName: Name +) : AbstractVisualObject(), VisualGroup, VisualObject3D { constructor(parent: VisualGroup3D, templateName: Name) : this(templateName) { this.parent = parent @@ -36,7 +33,6 @@ class Proxy private constructor(val templateName: Name) : AbstractVisualObject() override var rotation: Point3D? = null override var scale: Point3D? = null - @Serializable(ConfigSerializer::class) override var properties: Config? = null /** @@ -44,10 +40,12 @@ class Proxy private constructor(val templateName: Name) : AbstractVisualObject() */ val prototype: VisualObject3D get() = (parent as? VisualGroup3D)?.getPrototype(templateName) - ?: error("Template with name $templateName not found in $parent") + ?: error("Prototype with name $templateName not found in $parent") override val styleSheet: StyleSheet - get() = (parent as? VisualGroup)?.styleSheet ?: StyleSheet(this) + get() = parent?.styleSheet ?: StyleSheet( + this + ) override fun getProperty(name: Name, inherit: Boolean): MetaItem<*>? { return if (inherit) { @@ -89,7 +87,8 @@ class Proxy private constructor(val templateName: Name) : AbstractVisualObject() //override fun findAllStyles(): Laminate = Laminate((styles + prototype.styles).mapNotNull { findStyle(it) }) - inner class ProxyChild(val name: Name) : AbstractVisualObject(), VisualGroup { + inner class ProxyChild(val name: Name) : AbstractVisualObject(), + VisualGroup { val prototype: VisualObject get() = prototypeFor(name) @@ -155,20 +154,18 @@ val VisualObject.prototype: VisualObject /** * Create ref for existing prototype */ -inline fun VisualGroup3D.ref( +fun VisualGroup3D.ref( templateName: Name, - name: String = "", - block: Proxy.() -> Unit = {} -) = Proxy(this, templateName).apply(block).also { set(name, it) } + name: String = "" +): Proxy = Proxy(this, templateName).also { set(name, it) } /** * Add new proxy wrapping given object and automatically adding it to the prototypes */ fun VisualGroup3D.proxy( - templateName: Name, + name: String, obj: VisualObject3D, - name: String = "", - block: Proxy.() -> Unit = {} + templateName: Name = name.toName() ): Proxy { val existing = getPrototype(templateName) if (existing == null) { @@ -178,5 +175,14 @@ fun VisualGroup3D.proxy( } else if (existing != obj) { error("Can't add different prototype on top of existing one") } - return ref(templateName, name, block) + return ref(templateName, name) +} + +fun VisualGroup3D.proxyGroup( + name: String, + templateName: Name = name.toName(), + block: MutableVisualGroup.() -> Unit +): Proxy { + val group = VisualGroup3D().apply(block) + return proxy(name, group, templateName) } diff --git a/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/Sphere.kt b/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/Sphere.kt index b29af3c8..27b56397 100644 --- a/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/Sphere.kt +++ b/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/Sphere.kt @@ -2,10 +2,10 @@ package hep.dataforge.vis.spatial -import hep.dataforge.io.serialization.ConfigSerializer import hep.dataforge.meta.Config -import hep.dataforge.vis.common.AbstractVisualObject -import hep.dataforge.vis.common.set +import hep.dataforge.vis.AbstractVisualObject +import hep.dataforge.vis.MutableVisualGroup +import hep.dataforge.vis.set import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable import kotlinx.serialization.UseSerializers @@ -23,7 +23,6 @@ class Sphere( var theta: Float = PI.toFloat() ) : AbstractVisualObject(), VisualObject3D, Shape { - @Serializable(ConfigSerializer::class) override var properties: Config? = null override var position: Point3D? = null @@ -61,7 +60,7 @@ class Sphere( } } -inline fun VisualGroup3D.sphere( +inline fun MutableVisualGroup.sphere( radius: Number, phi: Number = 2 * PI, theta: Number = PI, diff --git a/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/Tube.kt b/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/Tube.kt index d97ccce6..1f1de0f3 100644 --- a/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/Tube.kt +++ b/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/Tube.kt @@ -1,10 +1,10 @@ @file:UseSerializers(Point3DSerializer::class) package hep.dataforge.vis.spatial -import hep.dataforge.io.serialization.ConfigSerializer import hep.dataforge.meta.Config -import hep.dataforge.vis.common.AbstractVisualObject -import hep.dataforge.vis.common.set +import hep.dataforge.vis.AbstractVisualObject +import hep.dataforge.vis.MutableVisualGroup +import hep.dataforge.vis.set import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable import kotlinx.serialization.UseSerializers @@ -29,7 +29,6 @@ class Tube( override var rotation: Point3D? = null override var scale: Point3D? = null - @Serializable(ConfigSerializer::class) override var properties: Config? = null init { @@ -129,7 +128,7 @@ class Tube( } -inline fun VisualGroup3D.tube( +inline fun MutableVisualGroup.tube( r: Number, height: Number, innerRadius: Number = 0f, diff --git a/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/Visual3D.kt b/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/Visual3D.kt index cb362558..5e13b385 100644 --- a/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/Visual3D.kt +++ b/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/Visual3D.kt @@ -4,14 +4,12 @@ import hep.dataforge.context.AbstractPlugin import hep.dataforge.context.Context import hep.dataforge.context.PluginFactory import hep.dataforge.context.PluginTag -import hep.dataforge.io.serialization.ConfigSerializer -import hep.dataforge.io.serialization.MetaSerializer -import hep.dataforge.io.serialization.NameSerializer import hep.dataforge.meta.* import hep.dataforge.names.Name import hep.dataforge.names.toName -import hep.dataforge.vis.common.Visual -import hep.dataforge.vis.common.VisualObject +import hep.dataforge.vis.SimpleVisualGroup +import hep.dataforge.vis.Visual +import hep.dataforge.vis.VisualObject import kotlinx.serialization.json.Json import kotlinx.serialization.json.JsonConfiguration import kotlinx.serialization.modules.SerializersModule @@ -39,29 +37,28 @@ class Visual3D(meta: Meta) : AbstractPlugin(meta) { val serialModule = SerializersModule { contextual(Point3DSerializer) contextual(Point2DSerializer) - contextual(NameSerializer) - contextual(NameTokenSerializer) - contextual(MetaSerializer) - contextual(ConfigSerializer) polymorphic(VisualObject::class, VisualObject3D::class) { - VisualGroup3D::class with VisualGroup3D.serializer() - Proxy::class with Proxy.serializer() - Composite::class with Composite.serializer() - Tube::class with Tube.serializer() - Box::class with Box.serializer() - Convex::class with Convex.serializer() - Extruded::class with Extruded.serializer() - addSubclass(PolyLine.serializer()) - addSubclass(Label3D.serializer()) + subclass(SimpleVisualGroup.serializer()) + subclass(VisualGroup3D.serializer()) + subclass(Proxy.serializer()) + subclass(Composite.serializer()) + subclass(Tube.serializer()) + subclass(Box.serializer()) + subclass(Convex.serializer()) + subclass(Extruded.serializer()) + subclass(PolyLine.serializer()) + subclass(Label3D.serializer()) + subclass(Sphere.serializer()) } } - val json = Json( + internal val json = Json( JsonConfiguration( prettyPrint = true, useArrayPolymorphism = false, - encodeDefaults = false + encodeDefaults = false, + ignoreUnknownKeys = true ), context = serialModule ) diff --git a/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/VisualGroup3D.kt b/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/VisualGroup3D.kt index 402290f8..ba12fef2 100644 --- a/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/VisualGroup3D.kt +++ b/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/VisualGroup3D.kt @@ -1,48 +1,49 @@ @file:UseSerializers( - Point3DSerializer::class, - ConfigSerializer::class, - NameTokenSerializer::class, - NameSerializer::class, - MetaSerializer::class + Point3DSerializer::class ) package hep.dataforge.vis.spatial -import hep.dataforge.io.serialization.ConfigSerializer -import hep.dataforge.io.serialization.MetaSerializer -import hep.dataforge.io.serialization.NameSerializer import hep.dataforge.meta.Config import hep.dataforge.names.Name import hep.dataforge.names.NameToken import hep.dataforge.names.asName -import hep.dataforge.names.isEmpty -import hep.dataforge.vis.common.AbstractVisualGroup -import hep.dataforge.vis.common.StyleSheet -import hep.dataforge.vis.common.VisualObject -import hep.dataforge.vis.common.set +import hep.dataforge.vis.* import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable import kotlinx.serialization.UseSerializers import kotlin.collections.set +interface PrototypeHolder { + val parent: VisualGroup? + val prototypes: MutableVisualGroup? +} + /** * Represents 3-dimensional Visual Group */ @Serializable @SerialName("group.3d") -class VisualGroup3D : AbstractVisualGroup(), VisualObject3D { +class VisualGroup3D : AbstractVisualGroup(), VisualObject3D, PrototypeHolder { override var styleSheet: StyleSheet? = null - private set /** * A container for templates visible inside this group */ - var prototypes: VisualGroup3D? = null - set(value) { - value?.parent = this - field = value - } + @Serializable(PrototypesSerializer::class) + override var prototypes: MutableVisualGroup? = null + private set + + /** + * Create or edit prototype node as a group + */ + fun prototypes(builder: MutableVisualGroup.() -> Unit): Unit { + (prototypes ?: Prototypes().also { + attach(it) + prototypes = it + }).run(builder) + } //FIXME to be lifted to AbstractVisualGroup after https://github.com/Kotlin/kotlinx.serialization/issues/378 is fixed override var properties: Config? = null @@ -55,38 +56,18 @@ class VisualGroup3D : AbstractVisualGroup(), VisualObject3D { private val _children = HashMap() override val children: Map get() = _children -// init { -// //Do after deserialization -// attachChildren() -// } - override fun attachChildren() { prototypes?.parent = this prototypes?.attachChildren() super.attachChildren() } - /** - * Update or create stylesheet - */ - fun styleSheet(block: StyleSheet.() -> Unit) { - val res = styleSheet ?: StyleSheet(this).also { styleSheet = it } - res.block() - } - override fun removeChild(token: NameToken) { - _children.remove(token)?.run { parent = null } - childrenChanged(token.asName(), null) + _children.remove(token)?.apply { parent = null } } override fun setChild(token: NameToken, child: VisualObject) { - if (child.parent == null) { - child.parent = this - } else if (child.parent !== this) { - error("Can't reassign existing parent for $child") - } _children[token] = child - childrenChanged(token.asName(), child) } // /** @@ -94,25 +75,13 @@ class VisualGroup3D : AbstractVisualGroup(), VisualObject3D { // */ // override fun addStatic(child: VisualObject) = setChild(NameToken("@static(${child.hashCode()})"), child) - override fun createGroup(name: Name): VisualGroup3D { - return when { - name.isEmpty() -> error("Should be unreachable") - name.length == 1 -> { - val token = name.first()!! - when (val current = children[token]) { - null -> VisualGroup3D().also { setChild(token, it) } - is VisualGroup3D -> current - else -> error("Can't create group with name $name because it exists and not a group") - } - } - else -> createGroup(name.first()!!.asName()).createGroup(name.cutFirst()) - } - } + override fun createGroup(): VisualGroup3D = VisualGroup3D() + companion object { // val PROTOTYPES_KEY = NameToken("@prototypes") - fun fromJson(json: String): VisualGroup3D = + fun parseJson(json: String): VisualGroup3D = Visual3D.json.parse(serializer(), json).also { it.attachChildren() } } } @@ -120,21 +89,50 @@ class VisualGroup3D : AbstractVisualGroup(), VisualObject3D { /** * Ger a prototype redirecting the request to the parent if prototype is not found */ -tailrec fun VisualGroup3D.getPrototype(name: Name): VisualObject3D? = +tailrec fun PrototypeHolder.getPrototype(name: Name): VisualObject3D? = prototypes?.get(name) as? VisualObject3D ?: (parent as? VisualGroup3D)?.getPrototype(name) /** - * Create or edit prototype node as a group + * Define a group with given [name], attach it to this parent and return it. */ -inline fun VisualGroup3D.prototypes(builder: VisualGroup3D.() -> Unit): Unit { - (prototypes ?: VisualGroup3D().also { prototypes = it }).run(builder) -} - -/** - * Define a group with given [key], attach it to this parent and return it. - */ -fun VisualGroup3D.group(key: String = "", action: VisualGroup3D.() -> Unit = {}): VisualGroup3D = +fun MutableVisualGroup.group(name: String = "", action: VisualGroup3D.() -> Unit = {}): VisualGroup3D = VisualGroup3D().apply(action).also { - set(key, it) + set(name, it) } +internal class Prototypes( + override var children: MutableMap = LinkedHashMap() +) : AbstractVisualGroup(), MutableVisualGroup, PrototypeHolder { + + override var styleSheet: StyleSheet? + get() = null + set(_) { + error("Can't define stylesheet for prototypes block") + } + + override fun removeChild(token: NameToken) { + children.remove(token) + childrenChanged(token.asName(), null) + } + + override fun setChild(token: NameToken, child: VisualObject) { + children[token] = child + } + + override fun createGroup() = SimpleVisualGroup() + + override var properties: Config? + get() = null + set(_) { + error("Can't define properties for prototypes block") + } + + override val prototypes: MutableVisualGroup get() = this + + override fun attachChildren() { + children.values.forEach { + it.parent = parent + (it as? VisualGroup)?.attachChildren() + } + } +} diff --git a/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/VisualObject3D.kt b/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/VisualObject3D.kt index 8e94ed65..463326f4 100644 --- a/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/VisualObject3D.kt +++ b/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/VisualObject3D.kt @@ -1,13 +1,15 @@ -@file:UseSerializers(Point3DSerializer::class, NameSerializer::class, NameTokenSerializer::class) +@file:UseSerializers(Point3DSerializer::class) package hep.dataforge.vis.spatial -import hep.dataforge.io.serialization.NameSerializer import hep.dataforge.meta.* +import hep.dataforge.meta.descriptors.NodeDescriptor import hep.dataforge.names.asName import hep.dataforge.names.plus import hep.dataforge.output.Renderer -import hep.dataforge.vis.common.VisualObject +import hep.dataforge.values.ValueType +import hep.dataforge.values.asValue +import hep.dataforge.vis.VisualObject import hep.dataforge.vis.spatial.VisualObject3D.Companion.DETAIL_KEY import hep.dataforge.vis.spatial.VisualObject3D.Companion.IGNORE_KEY import hep.dataforge.vis.spatial.VisualObject3D.Companion.LAYER_KEY @@ -25,7 +27,8 @@ interface VisualObject3D : VisualObject { companion object { val VISIBLE_KEY = "visible".asName() -// val SELECTED_KEY = "selected".asName() + + // val SELECTED_KEY = "selected".asName() val DETAIL_KEY = "detail".asName() val LAYER_KEY = "layer".asName() val IGNORE_KEY = "ignore".asName() @@ -55,6 +58,22 @@ interface VisualObject3D : VisualObject { val xScale = scale + x val yScale = scale + y val zScale = scale + z + + val descriptor by lazy { + NodeDescriptor { + defineValue(VISIBLE_KEY) { + type(ValueType.BOOLEAN) + default(true) + } + + defineItem(Material3D.MATERIAL_KEY.toString(), Material3D.descriptor) + +// Material3D.MATERIAL_COLOR_KEY put "#ffffff" +// Material3D.MATERIAL_OPACITY_KEY put 1.0 +// Material3D.MATERIAL_WIREFRAME_KEY put false + + } + } } } @@ -64,10 +83,10 @@ interface VisualObject3D : VisualObject { var VisualObject3D.layer: Int get() = getProperty(LAYER_KEY).int ?: 0 set(value) { - setProperty(LAYER_KEY, value) + setProperty(LAYER_KEY, value.asValue()) } -fun Renderer.render(meta: Meta = EmptyMeta, action: VisualGroup3D.() -> Unit) = +fun Renderer.render(meta: Meta = Meta.EMPTY, action: VisualGroup3D.() -> Unit) = render(VisualGroup3D().apply(action), meta) // Common properties @@ -86,7 +105,7 @@ enum class RotationOrder { */ var VisualObject3D.rotationOrder: RotationOrder get() = getProperty(VisualObject3D.rotationOrder).enum() ?: RotationOrder.XYZ - set(value) = setProperty(VisualObject3D.rotationOrder, value.name) + set(value) = setProperty(VisualObject3D.rotationOrder, value.name.asValue()) /** @@ -94,19 +113,19 @@ var VisualObject3D.rotationOrder: RotationOrder */ var VisualObject3D.detail: Int? get() = getProperty(DETAIL_KEY, false).int - set(value) = setProperty(DETAIL_KEY, value) + set(value) = setProperty(DETAIL_KEY, value?.asValue()) var VisualObject.visible: Boolean? get() = getProperty(VISIBLE_KEY).boolean - set(value) = setProperty(VISIBLE_KEY, value) + set(value) = setProperty(VISIBLE_KEY, value?.asValue()) /** * If this property is true, the object will be ignored on render. * Property is not inherited. */ var VisualObject.ignore: Boolean? - get() = getProperty(IGNORE_KEY,false).boolean - set(value) = setProperty(IGNORE_KEY, value) + get() = getProperty(IGNORE_KEY, false).boolean + set(value) = setProperty(IGNORE_KEY, value?.asValue()) //var VisualObject.selected: Boolean? // get() = getProperty(SELECTED_KEY).boolean diff --git a/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/World.kt b/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/World.kt deleted file mode 100644 index bc946987..00000000 --- a/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/World.kt +++ /dev/null @@ -1,10 +0,0 @@ -package hep.dataforge.vis.spatial - -import kotlin.math.PI - -object World { - val ZERO = Point3D(0.0, 0.0, 0.0) - val ONE = Point3D(1.0, 1.0, 1.0) -} - -const val PI2: Float = 2 * PI.toFloat() \ No newline at end of file diff --git a/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/geometry.kt b/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/geometry.kt index 75336e60..f88528bb 100644 --- a/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/geometry.kt +++ b/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/geometry.kt @@ -1,9 +1,16 @@ package hep.dataforge.vis.spatial import hep.dataforge.meta.Meta -import hep.dataforge.meta.buildMeta 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) +} + +const val PI2: Float = 2 * PI.toFloat() expect class Point2D(x: Number, y: Number) { var x: Double @@ -13,7 +20,7 @@ expect class Point2D(x: Number, y: Number) { operator fun Point2D.component1() = x operator fun Point2D.component2() = y -fun Point2D.toMeta() = buildMeta { +fun Point2D.toMeta() = Meta { VisualObject3D.x put x VisualObject3D.y put y } @@ -34,7 +41,7 @@ operator fun Point3D.component3() = z fun Meta.point3D() = Point3D(this["x"].number ?: 0, this["y"].number ?: 0, this["y"].number ?: 0) -fun Point3D.toMeta() = buildMeta { +fun Point3D.toMeta() = Meta { VisualObject3D.x put x VisualObject3D.y put y VisualObject3D.z put z diff --git a/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/serialization.kt b/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/serialization.kt index 37115129..d4164529 100644 --- a/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/serialization.kt +++ b/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/serialization.kt @@ -1,17 +1,19 @@ package hep.dataforge.vis.spatial -import hep.dataforge.io.serialization.descriptor +import hep.dataforge.meta.double import hep.dataforge.names.NameToken -import hep.dataforge.names.toName +import hep.dataforge.vis.MutableVisualGroup +import hep.dataforge.vis.VisualGroup +import hep.dataforge.vis.VisualObject import kotlinx.serialization.* -import kotlinx.serialization.internal.DoubleSerializer -import kotlinx.serialization.internal.StringDescriptor -import kotlinx.serialization.internal.nullable +import kotlinx.serialization.builtins.MapSerializer +import kotlinx.serialization.builtins.nullable +import kotlinx.serialization.builtins.serializer inline fun Decoder.decodeStructure( desc: SerialDescriptor, vararg typeParams: KSerializer<*> = emptyArray(), - crossinline block: CompositeDecoder.() -> R + crossinline block: CompositeDecoder.() -> R ): R { val decoder = beginStructure(desc, *typeParams) val res = decoder.block() @@ -31,7 +33,7 @@ inline fun Encoder.encodeStructure( @Serializer(Point3D::class) object Point3DSerializer : KSerializer { - override val descriptor: SerialDescriptor = descriptor("hep.dataforge.vis.spatial.Point3D") { + override val descriptor: SerialDescriptor = SerialDescriptor("hep.dataforge.vis.spatial.Point3D") { double("x", true) double("y", true) double("z", true) @@ -45,28 +47,28 @@ object Point3DSerializer : KSerializer { loop@ while (true) { when (val i = decodeElementIndex(descriptor)) { CompositeDecoder.READ_DONE -> break@loop - 0 -> x = decodeNullableSerializableElement(descriptor, 0, DoubleSerializer.nullable) ?: 0.0 - 1 -> y = decodeNullableSerializableElement(descriptor, 1, DoubleSerializer.nullable) ?: 0.0 - 2 -> z = decodeNullableSerializableElement(descriptor, 2, DoubleSerializer.nullable) ?: 0.0 + 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 else -> throw SerializationException("Unknown index $i") } } } - return Point3D(x?:0.0, y?:0.0, z?:0.0) + return Point3D(x ?: 0.0, y ?: 0.0, z ?: 0.0) } - override fun serialize(encoder: Encoder, obj: Point3D) { + override fun serialize(encoder: Encoder, value: Point3D) { encoder.encodeStructure(descriptor) { - if (obj.x != 0.0) encodeDoubleElement(descriptor, 0, obj.x) - if (obj.y != 0.0) encodeDoubleElement(descriptor, 1, obj.y) - if (obj.z != 0.0) encodeDoubleElement(descriptor, 2, obj.z) + if (value.x != 0.0) encodeDoubleElement(descriptor, 0, value.x) + if (value.y != 0.0) encodeDoubleElement(descriptor, 1, value.y) + if (value.z != 0.0) encodeDoubleElement(descriptor, 2, value.z) } } } @Serializer(Point2D::class) object Point2DSerializer : KSerializer { - override val descriptor: SerialDescriptor = descriptor("hep.dataforge.vis.spatial.Point2D") { + override val descriptor: SerialDescriptor = SerialDescriptor("hep.dataforge.vis.spatial.Point2D") { double("x", true) double("y", true) } @@ -78,32 +80,48 @@ object Point2DSerializer : KSerializer { loop@ while (true) { when (val i = decodeElementIndex(descriptor)) { CompositeDecoder.READ_DONE -> break@loop - 0 -> x = decodeNullableSerializableElement(descriptor, 0, DoubleSerializer.nullable) ?: 0.0 - 1 -> y = decodeNullableSerializableElement(descriptor, 1, DoubleSerializer.nullable) ?: 0.0 + 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") } } } - return Point2D(x?:0.0, y?:0.0) + return Point2D(x ?: 0.0, y ?: 0.0) } - override fun serialize(encoder: Encoder, obj: Point2D) { + override fun serialize(encoder: Encoder, value: Point2D) { encoder.encodeStructure(descriptor) { - if (obj.x != 0.0) encodeDoubleElement(descriptor, 0, obj.x) - if (obj.y != 0.0) encodeDoubleElement(descriptor, 1, obj.y) + if (value.x != 0.0) encodeDoubleElement(descriptor, 0, value.x) + if (value.y != 0.0) encodeDoubleElement(descriptor, 1, value.y) } } } -@Serializer(NameToken::class) -object NameTokenSerializer : KSerializer { - override val descriptor: SerialDescriptor = StringDescriptor.withName("NameToken") +@Serializer(MutableVisualGroup::class) +internal object PrototypesSerializer : KSerializer { - override fun deserialize(decoder: Decoder): NameToken { - return decoder.decodeString().toName().first()!! + private val mapSerializer: KSerializer> = + MapSerializer( + NameToken.serializer(), + VisualObject.serializer() + ) + + override val descriptor: SerialDescriptor get() = mapSerializer.descriptor + + override fun deserialize(decoder: Decoder): MutableVisualGroup { + val map = mapSerializer.deserialize(decoder) + return Prototypes(map as? MutableMap ?: LinkedHashMap(map)) } - override fun serialize(encoder: Encoder, obj: NameToken) { - encoder.encodeString(obj.toString()) + override fun serialize(encoder: Encoder, value: MutableVisualGroup) { + mapSerializer.serialize(encoder, value.children) + } +} + +fun VisualObject.stringify(): String = Visual3D.json.stringify(VisualObject.serializer(), this) + +fun VisualObject.Companion.parseJson(str: String) = Visual3D.json.parse(VisualObject.serializer(), str).also { + if(it is VisualGroup){ + it.attachChildren() } } \ No newline at end of file diff --git a/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/specifications/AxesSpec.kt b/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/specifications/Axes.kt similarity index 60% rename from dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/specifications/AxesSpec.kt rename to dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/specifications/Axes.kt index b46b9f4d..eace3211 100644 --- a/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/specifications/AxesSpec.kt +++ b/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/specifications/Axes.kt @@ -2,16 +2,13 @@ package hep.dataforge.vis.spatial.specifications import hep.dataforge.meta.* -class AxesSpec(override val config: Config) : Specific { +class Axes : Scheme() { var visible by boolean(!config.isEmpty()) var size by double(AXIS_SIZE) var width by double(AXIS_WIDTH) - companion object : Specification { - override fun wrap(config: Config): AxesSpec = AxesSpec(config) - + companion object : SchemeSpec(::Axes) { const val AXIS_SIZE = 1000.0 const val AXIS_WIDTH = 3.0 - } } \ No newline at end of file diff --git a/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/specifications/CameraSpec.kt b/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/specifications/Camera.kt similarity index 69% rename from dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/specifications/CameraSpec.kt rename to dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/specifications/Camera.kt index eb23472f..0ff4534b 100644 --- a/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/specifications/CameraSpec.kt +++ b/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/specifications/Camera.kt @@ -1,10 +1,14 @@ package hep.dataforge.vis.spatial.specifications -import hep.dataforge.meta.* +import hep.dataforge.meta.Scheme +import hep.dataforge.meta.SchemeSpec +import hep.dataforge.meta.double +import hep.dataforge.meta.int import kotlin.math.PI -class CameraSpec(override val config: Config) : Specific { +class Camera : Scheme() { var fov by int(FIELD_OF_VIEW) + //var aspect by double(1.0) var nearClip by double(NEAR_CLIP) var farClip by double(FAR_CLIP) @@ -14,11 +18,10 @@ class CameraSpec(override val config: Config) : Specific { var latitude by double(INITIAL_LATITUDE) val zenith: Double get() = PI / 2 - latitude - companion object : Specification { - override fun wrap(config: Config): CameraSpec = CameraSpec(config) + companion object : SchemeSpec(::Camera) { const val INITIAL_DISTANCE = 300.0 const val INITIAL_AZIMUTH = 0.0 - const val INITIAL_LATITUDE = PI/6 + const val INITIAL_LATITUDE = PI / 6 const val NEAR_CLIP = 0.1 const val FAR_CLIP = 10000.0 const val FIELD_OF_VIEW = 75 diff --git a/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/specifications/Canvas.kt b/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/specifications/Canvas.kt new file mode 100644 index 00000000..ba762d9a --- /dev/null +++ b/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/specifications/Canvas.kt @@ -0,0 +1,15 @@ +package hep.dataforge.vis.spatial.specifications + +import hep.dataforge.meta.Scheme +import hep.dataforge.meta.SchemeSpec +import hep.dataforge.meta.int +import hep.dataforge.meta.spec + +class Canvas : 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) + + companion object : SchemeSpec(::Canvas) +} \ No newline at end of file diff --git a/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/specifications/CanvasSpec.kt b/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/specifications/CanvasSpec.kt deleted file mode 100644 index d9cbded6..00000000 --- a/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/specifications/CanvasSpec.kt +++ /dev/null @@ -1,15 +0,0 @@ -package hep.dataforge.vis.spatial.specifications - -import hep.dataforge.meta.* - -class CanvasSpec(override val config: Config) : Specific { - var axes by spec(AxesSpec) - var camera by spec(CameraSpec) - var controls by spec(ControlsSpec) - var minSize by int(300) - - companion object: Specification{ - override fun wrap(config: Config): CanvasSpec = CanvasSpec(config) - - } -} \ No newline at end of file diff --git a/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/specifications/Controls.kt b/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/specifications/Controls.kt new file mode 100644 index 00000000..6b7de59c --- /dev/null +++ b/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/specifications/Controls.kt @@ -0,0 +1,9 @@ +package hep.dataforge.vis.spatial.specifications + +import hep.dataforge.meta.Scheme +import hep.dataforge.meta.SchemeSpec + + +class Controls : Scheme() { + companion object : SchemeSpec(::Controls) +} \ No newline at end of file diff --git a/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/specifications/ControlsSpec.kt b/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/specifications/ControlsSpec.kt deleted file mode 100644 index 2a828766..00000000 --- a/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/specifications/ControlsSpec.kt +++ /dev/null @@ -1,11 +0,0 @@ -package hep.dataforge.vis.spatial.specifications - -import hep.dataforge.meta.Config -import hep.dataforge.meta.Specific -import hep.dataforge.meta.Specification - -class ControlsSpec(override val config: Config) : Specific { - companion object : Specification { - override fun wrap(config: Config): ControlsSpec = ControlsSpec(config) - } -} \ No newline at end of file diff --git a/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/transform/RemoveSingleChild.kt b/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/transform/RemoveSingleChild.kt index 636b9cc1..309bc873 100644 --- a/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/transform/RemoveSingleChild.kt +++ b/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/transform/RemoveSingleChild.kt @@ -2,9 +2,9 @@ package hep.dataforge.vis.spatial.transform import hep.dataforge.meta.update import hep.dataforge.names.asName -import hep.dataforge.vis.common.MutableVisualGroup -import hep.dataforge.vis.common.VisualGroup -import hep.dataforge.vis.common.VisualObject +import hep.dataforge.vis.MutableVisualGroup +import hep.dataforge.vis.VisualGroup +import hep.dataforge.vis.VisualObject import hep.dataforge.vis.spatial.* internal fun mergeChild(parent: VisualGroup, child: VisualObject): VisualObject { diff --git a/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/transform/UnRef.kt b/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/transform/UnRef.kt index c96be89c..e619a8c5 100644 --- a/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/transform/UnRef.kt +++ b/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/transform/UnRef.kt @@ -2,11 +2,10 @@ package hep.dataforge.vis.spatial.transform import hep.dataforge.names.Name import hep.dataforge.names.asName -import hep.dataforge.vis.common.MutableVisualGroup -import hep.dataforge.vis.common.VisualGroup +import hep.dataforge.vis.MutableVisualGroup +import hep.dataforge.vis.VisualGroup import hep.dataforge.vis.spatial.Proxy import hep.dataforge.vis.spatial.VisualGroup3D -import hep.dataforge.vis.spatial.prototypes object UnRef : VisualTreeTransform() { private fun VisualGroup.countRefs(): Map { diff --git a/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/transform/VisualTreeTransform.kt b/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/transform/VisualTreeTransform.kt index 596aad56..88c6fd12 100644 --- a/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/transform/VisualTreeTransform.kt +++ b/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/transform/VisualTreeTransform.kt @@ -1,6 +1,6 @@ package hep.dataforge.vis.spatial.transform -import hep.dataforge.vis.common.VisualObject +import hep.dataforge.vis.VisualObject /** * A root class for [VisualObject] tree optimization diff --git a/dataforge-vis-spatial/src/commonTest/kotlin/hep/dataforge/vis/spatial/ConvexTest.kt b/dataforge-vis-spatial/src/commonTest/kotlin/hep/dataforge/vis/spatial/ConvexTest.kt index 0c2b4143..62482282 100644 --- a/dataforge-vis-spatial/src/commonTest/kotlin/hep/dataforge/vis/spatial/ConvexTest.kt +++ b/dataforge-vis-spatial/src/commonTest/kotlin/hep/dataforge/vis/spatial/ConvexTest.kt @@ -1,8 +1,9 @@ package hep.dataforge.vis.spatial -import hep.dataforge.io.toMeta import hep.dataforge.meta.MetaItem import hep.dataforge.meta.getIndexed +import hep.dataforge.meta.node +import hep.dataforge.meta.toMetaItem import kotlin.test.Test import kotlin.test.assertEquals @@ -26,9 +27,9 @@ class ConvexTest { val convex = group.first() as Convex val json = Visual3D.json.toJson(Convex.serializer(), convex) - val meta = json.toMeta() + val meta = json.toMetaItem().node!! - val points = meta.getIndexed("points").values.map { (it as MetaItem.NodeItem<*>).node.point3D()} + val points = meta.getIndexed("points").values.map { (it as MetaItem.NodeItem<*>).node.point3D() } assertEquals(8, points.count()) assertEquals(8, convex.points.size) diff --git a/dataforge-vis-spatial/src/commonTest/kotlin/hep/dataforge/vis/spatial/GroupTest.kt b/dataforge-vis-spatial/src/commonTest/kotlin/hep/dataforge/vis/spatial/GroupTest.kt index 2608b53a..e5d6153d 100644 --- a/dataforge-vis-spatial/src/commonTest/kotlin/hep/dataforge/vis/spatial/GroupTest.kt +++ b/dataforge-vis-spatial/src/commonTest/kotlin/hep/dataforge/vis/spatial/GroupTest.kt @@ -1,7 +1,7 @@ package hep.dataforge.vis.spatial -import hep.dataforge.vis.common.Colors -import hep.dataforge.vis.common.get +import hep.dataforge.vis.Colors +import hep.dataforge.vis.get import kotlin.math.PI import kotlin.test.Test import kotlin.test.assertEquals diff --git a/dataforge-vis-spatial/src/commonTest/kotlin/hep/dataforge/vis/spatial/PropertyTest.kt b/dataforge-vis-spatial/src/commonTest/kotlin/hep/dataforge/vis/spatial/PropertyTest.kt index fa15b905..9972b8c2 100644 --- a/dataforge-vis-spatial/src/commonTest/kotlin/hep/dataforge/vis/spatial/PropertyTest.kt +++ b/dataforge-vis-spatial/src/commonTest/kotlin/hep/dataforge/vis/spatial/PropertyTest.kt @@ -3,7 +3,7 @@ package hep.dataforge.vis.spatial import hep.dataforge.meta.int import hep.dataforge.meta.set import hep.dataforge.names.asName -import hep.dataforge.vis.common.useStyle +import hep.dataforge.vis.useStyle import kotlin.test.Test import kotlin.test.assertEquals diff --git a/dataforge-vis-spatial/src/commonTest/kotlin/hep/dataforge/vis/spatial/SerializationTest.kt b/dataforge-vis-spatial/src/commonTest/kotlin/hep/dataforge/vis/spatial/SerializationTest.kt index ea242679..6dd4cd5a 100644 --- a/dataforge-vis-spatial/src/commonTest/kotlin/hep/dataforge/vis/spatial/SerializationTest.kt +++ b/dataforge-vis-spatial/src/commonTest/kotlin/hep/dataforge/vis/spatial/SerializationTest.kt @@ -1,12 +1,12 @@ package hep.dataforge.vis.spatial -import hep.dataforge.vis.spatial.Visual3D.Companion.json -import kotlinx.serialization.ImplicitReflectionSerializer +import hep.dataforge.names.toName +import hep.dataforge.vis.VisualObject +import hep.dataforge.vis.get import kotlin.test.Test import kotlin.test.assertEquals class SerializationTest { - @ImplicitReflectionSerializer @Test fun testCubeSerialization() { val cube = Box(100f, 100f, 100f).apply { @@ -14,9 +14,30 @@ class SerializationTest { x = 100 z = -100 } - val string = json.stringify(Box.serializer(), cube) + val string = cube.stringify() println(string) - val newCube = json.parse(Box.serializer(), string) + val newCube = VisualObject.parseJson(string) assertEquals(cube.config, newCube.config) } + + @Test + fun testProxySerialization() { + val cube = Box(100f, 100f, 100f).apply { + color(222) + x = 100 + z = -100 + } + val group = VisualGroup3D().apply { + proxy("cube", cube) + proxyGroup("pg", "pg.content".toName()){ + sphere(50){ + x = -100 + } + } + } + val string = group.stringify() + println(string) + val reconstructed = VisualGroup3D.parseJson(string) + assertEquals(group["cube"]?.config, reconstructed["cube"]?.config) + } } \ No newline at end of file diff --git a/dataforge-vis-spatial/src/jsMain/kotlin/hep/dataforge/vis/spatial/three/ThreeCanvas.kt b/dataforge-vis-spatial/src/jsMain/kotlin/hep/dataforge/vis/spatial/three/ThreeCanvas.kt index 08717e92..71227c19 100644 --- a/dataforge-vis-spatial/src/jsMain/kotlin/hep/dataforge/vis/spatial/three/ThreeCanvas.kt +++ b/dataforge-vis-spatial/src/jsMain/kotlin/hep/dataforge/vis/spatial/three/ThreeCanvas.kt @@ -2,17 +2,17 @@ package hep.dataforge.vis.spatial.three import hep.dataforge.context.Context import hep.dataforge.meta.Meta -import hep.dataforge.meta.get +import hep.dataforge.meta.getProperty import hep.dataforge.meta.string import hep.dataforge.names.Name import hep.dataforge.names.plus import hep.dataforge.names.toName import hep.dataforge.output.Renderer -import hep.dataforge.vis.common.Colors +import hep.dataforge.vis.Colors import hep.dataforge.vis.spatial.VisualObject3D -import hep.dataforge.vis.spatial.specifications.CameraSpec -import hep.dataforge.vis.spatial.specifications.CanvasSpec -import hep.dataforge.vis.spatial.specifications.ControlsSpec +import hep.dataforge.vis.spatial.specifications.Camera +import hep.dataforge.vis.spatial.specifications.Canvas +import hep.dataforge.vis.spatial.specifications.Controls import hep.dataforge.vis.spatial.three.ThreeMaterials.HIGHLIGHT_MATERIAL import info.laht.threekt.WebGLRenderer import info.laht.threekt.cameras.PerspectiveCamera @@ -39,7 +39,7 @@ import kotlin.math.sin /** * */ -class ThreeCanvas(element: HTMLElement, val three: ThreePlugin, val spec: CanvasSpec) : Renderer { +class ThreeCanvas(element: HTMLElement, val three: ThreePlugin, val canvas: Canvas) : Renderer { override val context: Context get() = three.context @@ -53,15 +53,15 @@ class ThreeCanvas(element: HTMLElement, val three: ThreePlugin, val spec: Canvas var clickListener: ((Name) -> Unit)? = null - val axes = AxesHelper(spec.axes.size.toInt()).apply { - visible = spec.axes.visible + val axes = AxesHelper(canvas.axes.size.toInt()).apply { + visible = canvas.axes.visible } val scene: Scene = Scene().apply { add(axes) } - val camera = buildCamera(spec.camera) + val camera = buildCamera(canvas.camera) init { element.clear() @@ -90,7 +90,7 @@ class ThreeCanvas(element: HTMLElement, val three: ThreePlugin, val spec: Canvas } - addControls(renderer.domElement, spec.controls) + addControls(renderer.domElement, canvas.controls) fun animate() { val mesh = pick() @@ -108,7 +108,7 @@ class ThreeCanvas(element: HTMLElement, val three: ThreePlugin, val spec: Canvas element.appendChild(renderer.domElement) - renderer.setSize(max(spec.minSize, element.offsetWidth), max(spec.minSize, element.offsetWidth)) + renderer.setSize(max(canvas.minSize, element.offsetWidth), max(canvas.minSize, element.offsetWidth)) element.onresize = { renderer.setSize(element.offsetWidth, element.offsetWidth) @@ -142,7 +142,7 @@ class ThreeCanvas(element: HTMLElement, val three: ThreePlugin, val spec: Canvas } } - private fun buildCamera(spec: CameraSpec) = PerspectiveCamera( + private fun buildCamera(spec: Camera) = PerspectiveCamera( spec.fov, 1.0, spec.nearClip, @@ -153,8 +153,8 @@ class ThreeCanvas(element: HTMLElement, val three: ThreePlugin, val spec: Canvas translateZ(spec.distance * sin(spec.zenith) * cos(spec.azimuth)) } - private fun addControls(element: Node, controlsSpec: ControlsSpec) { - when (controlsSpec["type"].string) { + private fun addControls(element: Node, controls: Controls) { + when (controls.getProperty("type").string) { "trackball" -> TrackballControls(camera, element) else -> OrbitControls(camera, element) } @@ -211,5 +211,9 @@ class ThreeCanvas(element: HTMLElement, val three: ThreePlugin, val spec: Canvas } } -fun ThreePlugin.output(element: HTMLElement, spec: CanvasSpec = CanvasSpec.empty()): ThreeCanvas = - ThreeCanvas(element, this, spec) \ No newline at end of file +fun ThreePlugin.output(element: HTMLElement, spec: Canvas = Canvas.empty()): ThreeCanvas = + ThreeCanvas(element, this, spec) + +fun ThreePlugin.render(element: HTMLElement, obj: VisualObject3D, spec: Canvas = Canvas.empty()): Unit = + output(element, spec).render(obj) + diff --git a/dataforge-vis-spatial/src/jsMain/kotlin/hep/dataforge/vis/spatial/three/ThreeCanvasComponent.kt b/dataforge-vis-spatial/src/jsMain/kotlin/hep/dataforge/vis/spatial/three/ThreeCanvasComponent.kt new file mode 100644 index 00000000..01f0a30f --- /dev/null +++ b/dataforge-vis-spatial/src/jsMain/kotlin/hep/dataforge/vis/spatial/three/ThreeCanvasComponent.kt @@ -0,0 +1,56 @@ +package hep.dataforge.vis.spatial.three + +import hep.dataforge.context.Global +import hep.dataforge.vis.spatial.VisualObject3D +import hep.dataforge.vis.spatial.specifications.Canvas +import kotlinx.html.id +import org.w3c.dom.HTMLElement +import react.RBuilder +import react.RComponent +import react.RProps +import react.RState +import react.dom.div +import kotlin.browser.document +import kotlin.dom.clear + +interface ThreeCanvasProps : RProps { + var obj: VisualObject3D + var canvasId: String + var options: Canvas +} + +class ThreeCanvasComponent : RComponent() { + + private val three: ThreePlugin = Global.plugins.fetch(ThreePlugin) + + override fun componentDidMount() { + val element = document.getElementById(props.canvasId) as? HTMLElement + ?: error("Element with id 'canvas' not found on page") + val output = three.output(element, props.options) + output.render(props.obj) + } + + override fun componentWillUnmount() { + val element = document.getElementById(props.canvasId) as? HTMLElement + ?: error("Element with id 'canvas' not found on page") + element.clear() + } + + override fun RBuilder.render() { + div { + attrs { + id = props.canvasId + } + } + } +} + +fun RBuilder.threeCanvas(object3D: VisualObject3D, id: String = "threeCanvas", options: Canvas.() -> Unit = {}) { + child(ThreeCanvasComponent::class) { + attrs { + this.obj = object3D + this.canvasId = id + this.options = Canvas.invoke(options) + } + } +} \ No newline at end of file diff --git a/dataforge-vis-spatial/src/jsMain/kotlin/hep/dataforge/vis/spatial/three/ThreeFactory.kt b/dataforge-vis-spatial/src/jsMain/kotlin/hep/dataforge/vis/spatial/three/ThreeFactory.kt index 6828cd7b..38d1bfb5 100644 --- a/dataforge-vis-spatial/src/jsMain/kotlin/hep/dataforge/vis/spatial/three/ThreeFactory.kt +++ b/dataforge-vis-spatial/src/jsMain/kotlin/hep/dataforge/vis/spatial/three/ThreeFactory.kt @@ -3,7 +3,7 @@ package hep.dataforge.vis.spatial.three import hep.dataforge.names.Name import hep.dataforge.names.startsWith import hep.dataforge.provider.Type -import hep.dataforge.vis.common.VisualObject +import hep.dataforge.vis.VisualObject import hep.dataforge.vis.spatial.* import hep.dataforge.vis.spatial.Material3D.Companion.MATERIAL_KEY import hep.dataforge.vis.spatial.three.ThreeFactory.Companion.TYPE diff --git a/dataforge-vis-spatial/src/jsMain/kotlin/hep/dataforge/vis/spatial/three/ThreeMaterials.kt b/dataforge-vis-spatial/src/jsMain/kotlin/hep/dataforge/vis/spatial/three/ThreeMaterials.kt index 786c0efd..4ef25b5a 100644 --- a/dataforge-vis-spatial/src/jsMain/kotlin/hep/dataforge/vis/spatial/three/ThreeMaterials.kt +++ b/dataforge-vis-spatial/src/jsMain/kotlin/hep/dataforge/vis/spatial/three/ThreeMaterials.kt @@ -2,8 +2,8 @@ package hep.dataforge.vis.spatial.three import hep.dataforge.meta.* import hep.dataforge.values.ValueType -import hep.dataforge.vis.common.Colors -import hep.dataforge.vis.common.VisualObject +import hep.dataforge.vis.Colors +import hep.dataforge.vis.VisualObject import hep.dataforge.vis.spatial.Material3D import info.laht.threekt.materials.LineBasicMaterial import info.laht.threekt.materials.Material diff --git a/dataforge-vis-spatial/src/jsMain/kotlin/hep/dataforge/vis/spatial/three/ThreePlugin.kt b/dataforge-vis-spatial/src/jsMain/kotlin/hep/dataforge/vis/spatial/three/ThreePlugin.kt index e5c99efe..6c6aabeb 100644 --- a/dataforge-vis-spatial/src/jsMain/kotlin/hep/dataforge/vis/spatial/three/ThreePlugin.kt +++ b/dataforge-vis-spatial/src/jsMain/kotlin/hep/dataforge/vis/spatial/three/ThreePlugin.kt @@ -3,7 +3,7 @@ package hep.dataforge.vis.spatial.three import hep.dataforge.context.* import hep.dataforge.meta.Meta import hep.dataforge.names.* -import hep.dataforge.vis.common.VisualObject +import hep.dataforge.vis.VisualObject import hep.dataforge.vis.spatial.* import info.laht.threekt.core.Object3D import kotlin.collections.set diff --git a/dataforge-vis-spatial/src/jsMain/kotlin/hep/dataforge/vis/spatial/three/ThreeVisualObject.kt b/dataforge-vis-spatial/src/jsMain/kotlin/hep/dataforge/vis/spatial/three/ThreeVisualObject.kt index 5970a76d..6071b31e 100644 --- a/dataforge-vis-spatial/src/jsMain/kotlin/hep/dataforge/vis/spatial/three/ThreeVisualObject.kt +++ b/dataforge-vis-spatial/src/jsMain/kotlin/hep/dataforge/vis/spatial/three/ThreeVisualObject.kt @@ -2,9 +2,8 @@ package hep.dataforge.vis.spatial.three -import hep.dataforge.io.serialization.ConfigSerializer import hep.dataforge.meta.Config -import hep.dataforge.vis.common.AbstractVisualObject +import hep.dataforge.vis.AbstractVisualObject import hep.dataforge.vis.spatial.Point3D import hep.dataforge.vis.spatial.Point3DSerializer import hep.dataforge.vis.spatial.VisualObject3D @@ -26,7 +25,6 @@ class CustomThreeVisualObject(val threeFactory: ThreeFactory) : override var rotation: Point3D? = null override var scale: Point3D? = null - @Serializable(ConfigSerializer::class) override var properties: Config? = null override fun toObject3D(): Object3D = threeFactory(this) diff --git a/dataforge-vis-spatial/src/jsMain/kotlin/hep/dataforge/vis/spatial/three/csg.kt b/dataforge-vis-spatial/src/jsMain/kotlin/hep/dataforge/vis/spatial/three/csg.kt index 036f729a..615e4624 100644 --- a/dataforge-vis-spatial/src/jsMain/kotlin/hep/dataforge/vis/spatial/three/csg.kt +++ b/dataforge-vis-spatial/src/jsMain/kotlin/hep/dataforge/vis/spatial/three/csg.kt @@ -1,4 +1,4 @@ -@file:JsModule("@hi-level/three-csg") +@file:JsModule("three-csg-ts") @file:JsNonModule @file:Suppress( "INTERFACE_WITH_SUPERCLASS", diff --git a/dataforge-vis-spatial/src/jsMain/kotlin/hep/dataforge/vis/spatial/three/outputConfig.kt b/dataforge-vis-spatial/src/jsMain/kotlin/hep/dataforge/vis/spatial/three/outputConfig.kt index 70afb07d..d6042d01 100644 --- a/dataforge-vis-spatial/src/jsMain/kotlin/hep/dataforge/vis/spatial/three/outputConfig.kt +++ b/dataforge-vis-spatial/src/jsMain/kotlin/hep/dataforge/vis/spatial/three/outputConfig.kt @@ -1,7 +1,7 @@ package hep.dataforge.vis.spatial.three import hep.dataforge.js.requireJS -import hep.dataforge.vis.js.editor.accordion +import hep.dataforge.vis.editor.accordion import hep.dataforge.vis.spatial.Visual3D import hep.dataforge.vis.spatial.VisualGroup3D import kotlinx.html.InputType diff --git a/dataforge-vis-spatial/src/jvmMain/kotlin/hep/dataforge/vis/spatial/fx/FXCanvas3D.kt b/dataforge-vis-spatial/src/jvmMain/kotlin/hep/dataforge/vis/spatial/fx/FXCanvas3D.kt index 1704eeb2..499a2e5d 100644 --- a/dataforge-vis-spatial/src/jvmMain/kotlin/hep/dataforge/vis/spatial/fx/FXCanvas3D.kt +++ b/dataforge-vis-spatial/src/jvmMain/kotlin/hep/dataforge/vis/spatial/fx/FXCanvas3D.kt @@ -5,7 +5,7 @@ import hep.dataforge.context.ContextAware import hep.dataforge.meta.Meta import hep.dataforge.output.Renderer import hep.dataforge.vis.spatial.VisualObject3D -import hep.dataforge.vis.spatial.specifications.CanvasSpec +import hep.dataforge.vis.spatial.specifications.Canvas import javafx.application.Platform import javafx.beans.property.ObjectProperty import javafx.beans.property.SimpleObjectProperty @@ -14,7 +14,7 @@ import javafx.scene.paint.Color import org.fxyz3d.scene.Axes import tornadofx.* -class FXCanvas3D(val plugin: FX3DPlugin, val spec: CanvasSpec = CanvasSpec.empty()) : +class FXCanvas3D(val plugin: FX3DPlugin, val spec: Canvas = Canvas.empty()) : Fragment(), Renderer, ContextAware { override val context: Context get() = plugin.context diff --git a/dataforge-vis-spatial/src/jvmMain/kotlin/hep/dataforge/vis/spatial/fx/FXMaterials.kt b/dataforge-vis-spatial/src/jvmMain/kotlin/hep/dataforge/vis/spatial/fx/FXMaterials.kt index bdaf52dc..1e78d8d5 100644 --- a/dataforge-vis-spatial/src/jvmMain/kotlin/hep/dataforge/vis/spatial/fx/FXMaterials.kt +++ b/dataforge-vis-spatial/src/jvmMain/kotlin/hep/dataforge/vis/spatial/fx/FXMaterials.kt @@ -5,7 +5,7 @@ import hep.dataforge.meta.double import hep.dataforge.meta.get import hep.dataforge.meta.int import hep.dataforge.values.ValueType -import hep.dataforge.vis.common.Colors +import hep.dataforge.vis.Colors import hep.dataforge.vis.spatial.Material3D import javafx.scene.paint.Color import javafx.scene.paint.Material diff --git a/dataforge-vis-spatial/src/jvmMain/kotlin/hep/dataforge/vis/spatial/fx/FXProxyFactory.kt b/dataforge-vis-spatial/src/jvmMain/kotlin/hep/dataforge/vis/spatial/fx/FXProxyFactory.kt index 6052afcd..47900222 100644 --- a/dataforge-vis-spatial/src/jvmMain/kotlin/hep/dataforge/vis/spatial/fx/FXProxyFactory.kt +++ b/dataforge-vis-spatial/src/jvmMain/kotlin/hep/dataforge/vis/spatial/fx/FXProxyFactory.kt @@ -3,7 +3,7 @@ package hep.dataforge.vis.spatial.fx import hep.dataforge.names.Name import hep.dataforge.names.isEmpty import hep.dataforge.names.toName -import hep.dataforge.vis.common.VisualObject +import hep.dataforge.vis.VisualObject import hep.dataforge.vis.spatial.Proxy import javafx.scene.Group import javafx.scene.Node diff --git a/dataforge-vis-spatial/src/jvmMain/kotlin/hep/dataforge/vis/spatial/fx/OrbitControls.kt b/dataforge-vis-spatial/src/jvmMain/kotlin/hep/dataforge/vis/spatial/fx/OrbitControls.kt index aaa90ee9..ce3f2d7d 100644 --- a/dataforge-vis-spatial/src/jvmMain/kotlin/hep/dataforge/vis/spatial/fx/OrbitControls.kt +++ b/dataforge-vis-spatial/src/jvmMain/kotlin/hep/dataforge/vis/spatial/fx/OrbitControls.kt @@ -1,6 +1,5 @@ package hep.dataforge.vis.spatial.fx -import hep.dataforge.vis.spatial.specifications.CameraSpec import javafx.beans.InvalidationListener import javafx.beans.property.SimpleDoubleProperty import javafx.event.EventHandler @@ -15,6 +14,7 @@ import javafx.scene.transform.Rotate import javafx.scene.transform.Translate import tornadofx.* import kotlin.math.* +import hep.dataforge.vis.spatial.specifications.Camera as CameraSpec class OrbitControls internal constructor(camera: Camera, canvas: SubScene, spec: CameraSpec) { diff --git a/dataforge-vis-spatial/src/jvmMain/kotlin/hep/dataforge/vis/spatial/fx/VisualObjectFXBinding.kt b/dataforge-vis-spatial/src/jvmMain/kotlin/hep/dataforge/vis/spatial/fx/VisualObjectFXBinding.kt index faa7b843..2280723f 100644 --- a/dataforge-vis-spatial/src/jvmMain/kotlin/hep/dataforge/vis/spatial/fx/VisualObjectFXBinding.kt +++ b/dataforge-vis-spatial/src/jvmMain/kotlin/hep/dataforge/vis/spatial/fx/VisualObjectFXBinding.kt @@ -4,7 +4,7 @@ import hep.dataforge.meta.* import hep.dataforge.names.Name import hep.dataforge.names.startsWith import hep.dataforge.names.toName -import hep.dataforge.vis.common.VisualObject +import hep.dataforge.vis.VisualObject import javafx.application.Platform import javafx.beans.binding.ObjectBinding import tornadofx.* diff --git a/dataforge-vis-spatial-gdml/src/jvmMain/kotlin/hep/dataforge/vis/spatial/gdml/generateSchema.kt b/dataforge-vis-spatial/src/jvmMain/kotlin/hep/dataforge/vis/spatial/generateSchema.kt similarity index 58% rename from dataforge-vis-spatial-gdml/src/jvmMain/kotlin/hep/dataforge/vis/spatial/gdml/generateSchema.kt rename to dataforge-vis-spatial/src/jvmMain/kotlin/hep/dataforge/vis/spatial/generateSchema.kt index 53768de4..54a2c08d 100644 --- a/dataforge-vis-spatial-gdml/src/jvmMain/kotlin/hep/dataforge/vis/spatial/gdml/generateSchema.kt +++ b/dataforge-vis-spatial/src/jvmMain/kotlin/hep/dataforge/vis/spatial/generateSchema.kt @@ -1,23 +1,24 @@ -package hep.dataforge.vis.spatial.gdml +package hep.dataforge.vis.spatial -import hep.dataforge.meta.Meta -import hep.dataforge.vis.spatial.* +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 -internal val SerialDescriptor.jsonType - get() = 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.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("3d")||serialName.startsWith("group") + +private const val definitionNode = "\$defs" private fun SerialModule.enumerate(type: KClass<*>): Sequence { val list = ArrayList() @@ -60,13 +61,16 @@ private fun SerialModule.enumerate(type: KClass<*>): Sequence */ private fun jsonSchema(descriptor: SerialDescriptor, context: SerialModule): JsonObject { - if (descriptor.name in arrayOf( + if (descriptor.serialName in arrayOf( "hep.dataforge.vis.spatial.Point3D", + "hep.dataforge.vis.spatial.Point3D?", "hep.dataforge.vis.spatial.Point2D", - Meta::class.qualifiedName + "hep.dataforge.vis.spatial.Point2D?", + "hep.dataforge.meta.Meta", + "hep.dataforge.meta.Meta?" ) ) return json { - "\$ref" to "#/definitions/${descriptor.name}" + "\$ref" to "#/$definitionNode/${descriptor.serialName.replace("?", "")}" } @@ -79,37 +83,35 @@ private fun jsonSchema(descriptor: SerialDescriptor, context: SerialModule): Jso if (!isEnum && !isPolymorphic) descriptor.elementDescriptors().forEachIndexed { index, child -> val elementName = descriptor.getElementName(index) - properties[elementName] = when (elementName) { - "templates" -> json { - "\$ref" to "#/definitions/hep.dataforge.vis.spatial.VisualGroup3D" + val elementSchema = when (elementName) { + "properties" -> json { + "\$ref" to "#/$definitionNode/hep.dataforge.meta.Meta" } - "properties" -> json { - "\$ref" to "#/definitions/${Meta::class.qualifiedName}" - } - "first", "second" -> json{ - "\$ref" to "#/definitions/children" + "first", "second" -> json { + "\$ref" to "#/$definitionNode/children" } "styleSheet" -> json { "type" to "object" "additionalProperties" to json { - "\$ref" to "#/definitions/${Meta::class.qualifiedName}" + "\$ref" to "#/$definitionNode/hep.dataforge.meta.Meta" } } - in arrayOf("children") -> json { + in arrayOf("children", "prototypes") -> json { "type" to "object" "additionalProperties" to json { - "\$ref" to "#/definitions/children" + "\$ref" to "#/$definitionNode/children" } } else -> jsonSchema(child, context) } + properties[elementName] = elementSchema if (!descriptor.isElementOptional(index)) requiredProperties.add(elementName) } - val jsonType = descriptor.jsonType + val jsonType = descriptor.getJsonType() val objectData: MutableMap = mutableMapOf( - "description" to JsonLiteral(descriptor.name), + "description" to JsonLiteral(descriptor.serialName), "type" to JsonLiteral(jsonType) ) if (isEnum) { @@ -118,6 +120,11 @@ private fun jsonSchema(descriptor: SerialDescriptor, context: SerialModule): Jso } 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()) { @@ -140,9 +147,9 @@ fun main() { "children" to json { "anyOf" to jsonArray { context.enumerate(VisualObject3D::class).forEach { - if (it.name == "hep.dataforge.vis.spatial.VisualGroup3D") { + if (it.serialName == "hep.dataforge.vis.spatial.VisualGroup3D") { +json { - "\$ref" to "#/definitions/${it.name}" + "\$ref" to "#/$definitionNode/${it.serialName}" } } else { +jsonSchema(it, context) @@ -150,18 +157,47 @@ fun main() { } } } - "hep.dataforge.vis.spatial.Point3D" to jsonSchema(Point3DSerializer.descriptor, context) - "hep.dataforge.vis.spatial.Point2D" to jsonSchema(Point2DSerializer.descriptor, context) - "hep.dataforge.vis.spatial.VisualGroup3D" to jsonSchema(VisualGroup3D.serializer().descriptor, context) + "hep.dataforge.meta.Meta" to json { + "type" to "object" + } + "hep.dataforge.vis.spatial.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.vis.spatial.Point2D" to json { + "type" to "object" + "properties" to json { + "x" to json { + "type" to "number" + } + "y" to json { + "type" to "number" + } + } + } + "hep.dataforge.vis.spatial.VisualGroup3D" to jsonSchema( + VisualGroup3D.serializer().descriptor, + context + ) } println( - Json.indented.stringify( + JSON_PRETTY.stringify( JsonObjectSerializer, json { - "definitions" to definitions - "\$ref" to "#/definitions/hep.dataforge.vis.spatial.VisualGroup3D" + "\$defs" to definitions + "\$ref" to "#/$definitionNode/hep.dataforge.vis.spatial.VisualGroup3D" } ) ) diff --git a/demo/gdml/build.gradle.kts b/demo/gdml/build.gradle.kts index 7558d178..864255b6 100644 --- a/demo/gdml/build.gradle.kts +++ b/demo/gdml/build.gradle.kts @@ -1,11 +1,15 @@ -import org.openjfx.gradle.JavaFXOptions +import scientifik.DependencyConfiguration +import scientifik.FXModule +import scientifik.fx plugins { id("scientifik.mpp") - id("org.openjfx.javafxplugin") id("application") } +val fxVersion: String by rootProject.extra +fx(FXModule.CONTROLS, version = fxVersion, configuration = DependencyConfiguration.IMPLEMENTATION) + kotlin { jvm { @@ -27,18 +31,9 @@ kotlin { api(project(":dataforge-vis-spatial-gdml")) } } - jvmMain{ - dependencies { - api("org.fxyz3d:fxyz3d:0.5.2") - } - } } } application { mainClassName = "hep.dataforge.vis.spatial.gdml.demo.GDMLDemoAppKt" -} - -configure { - modules("javafx.controls") } \ No newline at end of file diff --git a/demo/gdml/src/commonTest/kotlin/hep/dataforge/vis/spatial/gdml/GDMLVisualTest.kt b/demo/gdml/src/commonTest/kotlin/hep/dataforge/vis/spatial/gdml/GDMLVisualTest.kt index bac4481e..5b6b1231 100644 --- a/demo/gdml/src/commonTest/kotlin/hep/dataforge/vis/spatial/gdml/GDMLVisualTest.kt +++ b/demo/gdml/src/commonTest/kotlin/hep/dataforge/vis/spatial/gdml/GDMLVisualTest.kt @@ -1,7 +1,9 @@ package hep.dataforge.vis.spatial.gdml +import hep.dataforge.meta.setProperty import hep.dataforge.meta.string import hep.dataforge.names.toName +import hep.dataforge.values.asValue import hep.dataforge.vis.spatial.Material3D import hep.dataforge.vis.spatial.gdml.demo.cubes import kotlin.test.Test @@ -12,7 +14,7 @@ class GDMLVisualTest { fun testPrototypeProperty() { val gdml = cubes() val visual = gdml.toVisual() - visual["composite000.segment0".toName()]?.setProperty(Material3D.MATERIAL_COLOR_KEY, "red") + visual["composite000.segment0".toName()]?.setProperty(Material3D.MATERIAL_COLOR_KEY, "red".asValue()) assertEquals("red", visual["composite000.segment0".toName()]?.getProperty(Material3D.MATERIAL_COLOR_KEY).string) } } \ No newline at end of file diff --git a/demo/gdml/src/jsMain/kotlin/hep/dataforge/vis/spatial/gdml/demo/GDMLDemoApp.kt b/demo/gdml/src/jsMain/kotlin/hep/dataforge/vis/spatial/gdml/demo/GDMLDemoApp.kt index 88a948f3..08c4207e 100644 --- a/demo/gdml/src/jsMain/kotlin/hep/dataforge/vis/spatial/gdml/demo/GDMLDemoApp.kt +++ b/demo/gdml/src/jsMain/kotlin/hep/dataforge/vis/spatial/gdml/demo/GDMLDemoApp.kt @@ -3,14 +3,12 @@ package hep.dataforge.vis.spatial.gdml.demo import hep.dataforge.context.Global import hep.dataforge.js.Application import hep.dataforge.js.startApplication -import hep.dataforge.meta.buildMeta -import hep.dataforge.meta.withBottom import hep.dataforge.names.Name import hep.dataforge.names.isEmpty -import hep.dataforge.vis.common.VisualGroup -import hep.dataforge.vis.common.VisualObject -import hep.dataforge.vis.js.editor.displayObjectTree -import hep.dataforge.vis.js.editor.displayPropertyEditor +import hep.dataforge.vis.VisualGroup +import hep.dataforge.vis.VisualObject +import hep.dataforge.vis.editor.objectTree +import hep.dataforge.vis.editor.visualPropertyEditor 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.Material3D.Companion.MATERIAL_WIREFRAME_KEY @@ -23,7 +21,6 @@ import hep.dataforge.vis.spatial.gdml.toVisual import hep.dataforge.vis.spatial.three.ThreePlugin import hep.dataforge.vis.spatial.three.displayCanvasControls import hep.dataforge.vis.spatial.three.output -import hep.dataforge.vis.spatial.visible import org.w3c.dom.* import org.w3c.files.FileList import org.w3c.files.FileReader @@ -139,7 +136,7 @@ private class GDMLDemoApp : Application { message("Converting GDML into DF-VIS format") gdml.toVisual(gdmlConfiguration) } - name.endsWith(".json") -> VisualGroup3D.fromJson(data) + name.endsWith(".json") -> VisualGroup3D.parseJson(data) else -> { window.alert("File extension is not recognized: $name") error("File extension is not recognized: $name") @@ -163,33 +160,38 @@ private class GDMLDemoApp : Application { visual is VisualGroup -> visual[name] ?: return else -> return } - editorElement.displayPropertyEditor(name, child) { item -> - //val descriptorMeta = Material3D.descriptor - val properties = item.allProperties() - val bottom = buildMeta { - VISIBLE_KEY put (item.visible ?: true) - if (item is VisualObject3D) { - MATERIAL_COLOR_KEY put "#ffffff" - MATERIAL_OPACITY_KEY put 1.0 - MATERIAL_WIREFRAME_KEY put false - } + editorElement.visualPropertyEditor(name, child) { + VISIBLE_KEY put true + if (child is VisualObject3D) { + MATERIAL_COLOR_KEY put "#ffffff" + MATERIAL_OPACITY_KEY put 1.0 + MATERIAL_WIREFRAME_KEY put false } - properties.withBottom(bottom) } +// editorElement.displayPropertyEditor(name, child) { item -> +// //val descriptorMeta = Material3D.descriptor +// +// val properties = item.allProperties() +// val bottom = Meta { +// VISIBLE_KEY put (item.visible ?: true) +// if (item is VisualObject3D) { +// MATERIAL_COLOR_KEY put "#ffffff" +// MATERIAL_OPACITY_KEY put 1.0 +// MATERIAL_WIREFRAME_KEY put false +// } +// } +// properties.withBottom(bottom) +// } } // canvas.clickListener = ::selectElement //tree.visualObjectTree(visual, editor::propertyEditor) - treeElement.displayObjectTree(visual) { treeName -> + treeElement.objectTree(visual) { treeName -> selectElement(treeName) canvas.highlight(treeName) } - canvas.render(visual) - - - canvas.render(visual) message(null) spinner(false) diff --git a/demo/gdml/src/jsMain/web/css/jsoneditor.min.css b/demo/gdml/src/jsMain/resources/css/jsoneditor.min.css similarity index 100% rename from demo/gdml/src/jsMain/web/css/jsoneditor.min.css rename to demo/gdml/src/jsMain/resources/css/jsoneditor.min.css diff --git a/demo/gdml/src/jsMain/web/css/main.css b/demo/gdml/src/jsMain/resources/css/main.css similarity index 100% rename from demo/gdml/src/jsMain/web/css/main.css rename to demo/gdml/src/jsMain/resources/css/main.css diff --git a/demo/gdml/src/jsMain/web/img/jsoneditor-icons.svg b/demo/gdml/src/jsMain/resources/img/jsoneditor-icons.svg similarity index 100% rename from demo/gdml/src/jsMain/web/img/jsoneditor-icons.svg rename to demo/gdml/src/jsMain/resources/img/jsoneditor-icons.svg diff --git a/demo/gdml/src/jsMain/web/index.html b/demo/gdml/src/jsMain/resources/index.html similarity index 100% rename from demo/gdml/src/jsMain/web/index.html rename to demo/gdml/src/jsMain/resources/index.html diff --git a/demo/gdml/src/jvmMain/kotlin/hep/dataforge/vis/spatial/gdml/demo/GDMLDemoApp.kt b/demo/gdml/src/jvmMain/kotlin/hep/dataforge/vis/spatial/gdml/demo/GDMLDemoApp.kt index ff07ebc6..9de54bc5 100644 --- a/demo/gdml/src/jvmMain/kotlin/hep/dataforge/vis/spatial/gdml/demo/GDMLDemoApp.kt +++ b/demo/gdml/src/jvmMain/kotlin/hep/dataforge/vis/spatial/gdml/demo/GDMLDemoApp.kt @@ -1,8 +1,8 @@ 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.editor.VisualObjectEditorFragment +import hep.dataforge.vis.editor.VisualObjectTreeFragment import hep.dataforge.vis.spatial.Material3D import hep.dataforge.vis.spatial.Visual3D import hep.dataforge.vis.spatial.VisualGroup3D diff --git a/demo/gdml/src/jvmMain/kotlin/hep/dataforge/vis/spatial/gdml/demo/readFile.kt b/demo/gdml/src/jvmMain/kotlin/hep/dataforge/vis/spatial/gdml/demo/readFile.kt index 532e1399..be567114 100644 --- a/demo/gdml/src/jvmMain/kotlin/hep/dataforge/vis/spatial/gdml/demo/readFile.kt +++ b/demo/gdml/src/jvmMain/kotlin/hep/dataforge/vis/spatial/gdml/demo/readFile.kt @@ -1,5 +1,7 @@ package hep.dataforge.vis.spatial.gdml.demo +import hep.dataforge.meta.setProperty +import hep.dataforge.values.asValue import hep.dataforge.vis.spatial.Material3D import hep.dataforge.vis.spatial.Visual3D import hep.dataforge.vis.spatial.VisualGroup3D @@ -18,7 +20,7 @@ fun Visual3D.Companion.readFile(file: File): VisualGroup3D = when { solidConfiguration = { parent, solid -> if (solid.name == "cave") { - setProperty(Material3D.MATERIAL_WIREFRAME_KEY, true) + setProperty(Material3D.MATERIAL_WIREFRAME_KEY, true.asValue()) } if (parent.physVolumes.isNotEmpty()) { useStyle("opaque") { @@ -28,19 +30,19 @@ fun Visual3D.Companion.readFile(file: File): VisualGroup3D = when { } } } - file.extension == "json" -> VisualGroup3D.fromJson(file.readText()) + file.extension == "json" -> VisualGroup3D.parseJson(file.readText()) file.name.endsWith("json.zip") -> { file.inputStream().use { val unzip = ZipInputStream(it, Charsets.UTF_8) - val text = unzip.readAllBytes().decodeToString() - VisualGroup3D.fromJson(text) + val text = unzip.readBytes().decodeToString() + VisualGroup3D.parseJson(text) } } file.name.endsWith("json.gz") -> { file.inputStream().use { val unzip = GZIPInputStream(it) - val text = unzip.readAllBytes().decodeToString() - VisualGroup3D.fromJson(text) + val text = unzip.readBytes().decodeToString() + VisualGroup3D.parseJson(text) } } else -> error("Unknown extension ${file.extension}") diff --git a/demo/gdml/src/jvmMain/kotlin/hep/dataforge/vis/spatial/gdml/demo/saveToJson.kt b/demo/gdml/src/jvmMain/kotlin/hep/dataforge/vis/spatial/gdml/demo/saveToJson.kt index f2491423..b069debe 100644 --- a/demo/gdml/src/jvmMain/kotlin/hep/dataforge/vis/spatial/gdml/demo/saveToJson.kt +++ b/demo/gdml/src/jvmMain/kotlin/hep/dataforge/vis/spatial/gdml/demo/saveToJson.kt @@ -5,6 +5,7 @@ import hep.dataforge.vis.spatial.VisualGroup3D 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.stringify import scientifik.gdml.GDML import java.io.File import java.nio.file.Paths @@ -14,6 +15,6 @@ fun main() { val visual = gdml.toVisual { lUnit = LUnit.CM } - val json = Visual3D.json.stringify(VisualGroup3D.serializer(), visual) + val json = visual.stringify() File("D:\\Work\\Projects\\gdml.kt\\gdml-source\\cubes.json").writeText(json) } \ No newline at end of file diff --git a/demo/gdml/src/jvmTest/kotlin/hep/dataforge/vis/spatial/FileSerializationTest.kt b/demo/gdml/src/jvmTest/kotlin/hep/dataforge/vis/spatial/FileSerializationTest.kt index 273c25ba..af51354b 100644 --- a/demo/gdml/src/jvmTest/kotlin/hep/dataforge/vis/spatial/FileSerializationTest.kt +++ b/demo/gdml/src/jvmTest/kotlin/hep/dataforge/vis/spatial/FileSerializationTest.kt @@ -1,15 +1,15 @@ package hep.dataforge.vis.spatial import hep.dataforge.names.asName -import org.junit.Test +import org.junit.jupiter.api.Test import kotlin.test.Ignore class FileSerializationTest { @Test @Ignore fun testFileRead(){ - val text = this::class.java.getResourceAsStream("/cubes.json").readAllBytes().decodeToString() - val visual = VisualGroup3D.fromJson(text) + val text = this::class.java.getResourceAsStream("/cubes.json").readBytes().decodeToString() + val visual = VisualGroup3D.parseJson(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 48b34d0b..53a05cd7 100644 --- a/demo/muon-monitor/build.gradle.kts +++ b/demo/muon-monitor/build.gradle.kts @@ -1,36 +1,25 @@ -import scientifik.useSerialization +import scientifik.jsDistDirectory plugins { id("scientifik.mpp") - //id("org.openjfx.javafxplugin") id("application") } group = "ru.mipt.npm" -useSerialization() - -val ktor_version = "1.3.0-rc" +val ktorVersion = "1.3.2" kotlin { - js { - browser { - webpackTask { - sourceMaps = true - } - } - } - - val installJS = tasks.getByName("installJsDist") + val installJS = tasks.getByName("jsBrowserDistribution") jvm { withJava() - compilations.findByName("main").apply { + compilations.findByName("jvmMain").apply { tasks.getByName("jvmProcessResources") { dependsOn(installJS) afterEvaluate { - from(installJS.destinationDir) + from(project.jsDistDirectory) } } } @@ -45,23 +34,29 @@ kotlin { jvmMain { dependencies { implementation("org.apache.commons:commons-math3:3.6.1") - implementation("io.ktor:ktor-server-cio:$ktor_version") - implementation("io.ktor:ktor-serialization:$ktor_version") + implementation("io.ktor:ktor-server-cio:$ktorVersion") + implementation("io.ktor:ktor-serialization:$ktorVersion") } } - jsMain{ - dependencies{ - implementation("io.ktor:ktor-client-js:$ktor_version") - implementation("io.ktor:ktor-client-serialization-js:$ktor_version") + jsMain { + dependencies { + 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")) } } } } application { - mainClassName = "ru.mipt.npm.muon.monitor.server/MMServerKt" + mainClassName = "ru.mipt.npm.muon.monitor.server.MMServerKt" } //configure { diff --git a/demo/muon-monitor/src/commonMain/kotlin/ru/mipt/npm/muon/monitor/Model.kt b/demo/muon-monitor/src/commonMain/kotlin/ru/mipt/npm/muon/monitor/Model.kt index e2d6afb0..b76be164 100644 --- a/demo/muon-monitor/src/commonMain/kotlin/ru/mipt/npm/muon/monitor/Model.kt +++ b/demo/muon-monitor/src/commonMain/kotlin/ru/mipt/npm/muon/monitor/Model.kt @@ -1,6 +1,6 @@ package ru.mipt.npm.muon.monitor -import hep.dataforge.vis.common.removeAll +import hep.dataforge.vis.removeAll import hep.dataforge.vis.spatial.* import ru.mipt.npm.muon.monitor.Monitor.CENTRAL_LAYER_Z import ru.mipt.npm.muon.monitor.Monitor.LOWER_LAYER_Z 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 3e680952..72656f95 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 @@ -3,15 +3,13 @@ package ru.mipt.npm.muon.monitor import hep.dataforge.context.Global import hep.dataforge.js.Application import hep.dataforge.js.startApplication -import hep.dataforge.meta.buildMeta -import hep.dataforge.meta.withBottom import hep.dataforge.names.Name import hep.dataforge.names.isEmpty -import hep.dataforge.vis.common.VisualGroup -import hep.dataforge.vis.common.VisualObject -import hep.dataforge.vis.js.editor.card -import hep.dataforge.vis.js.editor.displayObjectTree -import hep.dataforge.vis.js.editor.displayPropertyEditor +import hep.dataforge.vis.VisualGroup +import hep.dataforge.vis.VisualObject +import hep.dataforge.vis.editor.card +import hep.dataforge.vis.editor.objectTree +import hep.dataforge.vis.editor.visualPropertyEditor 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.Material3D.Companion.MATERIAL_WIREFRAME_KEY @@ -21,7 +19,6 @@ import hep.dataforge.vis.spatial.VisualObject3D.Companion.VISIBLE_KEY import hep.dataforge.vis.spatial.three.ThreePlugin import hep.dataforge.vis.spatial.three.displayCanvasControls import hep.dataforge.vis.spatial.three.output -import hep.dataforge.vis.spatial.visible import info.laht.threekt.math.Vector3 import io.ktor.client.HttpClient import io.ktor.client.features.json.JsonFeature @@ -31,6 +28,7 @@ import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.launch import kotlinx.html.js.button import kotlinx.html.js.onClickFunction +import kotlinx.serialization.json.Json import org.w3c.dom.HTMLElement import kotlin.browser.document import kotlin.dom.clear @@ -41,7 +39,7 @@ private class MMDemoApp : Application { private val connection = HttpClient { install(JsonFeature) { - serializer = KotlinxSerializer(Visual3D.json) + serializer = KotlinxSerializer(Json(context = Visual3D.serialModule)) } } @@ -66,7 +64,7 @@ private class MMDemoApp : Application { canvas.camera.layers.set(0) canvas.camera.position.z = -2000.0 canvas.camera.position.y = 500.0 - canvas.camera.lookAt(Vector3(0,0,0)) + canvas.camera.lookAt(Vector3(0, 0, 0)) settingsElement.displayCanvasControls(canvas) { card("Events") { button { @@ -94,26 +92,34 @@ private class MMDemoApp : Application { visual is VisualGroup -> visual[name] ?: return else -> return } - editorElement.displayPropertyEditor(name, child) { item -> - //val descriptorMeta = Material3D.descriptor - - val properties = item.allProperties() - val bottom = buildMeta { - VISIBLE_KEY put (item.visible ?: true) - if (item is VisualObject3D) { - MATERIAL_COLOR_KEY put "#ffffff" - MATERIAL_OPACITY_KEY put 1.0 - MATERIAL_WIREFRAME_KEY put false - } + editorElement.visualPropertyEditor(name, child) { + VISIBLE_KEY put true + if (child is VisualObject3D) { + MATERIAL_COLOR_KEY put "#ffffff" + MATERIAL_OPACITY_KEY put 1.0 + MATERIAL_WIREFRAME_KEY put false } - properties.withBottom(bottom) } +// editorElement.displayPropertyEditor(name, child) { item -> +// //val descriptorMeta = Material3D.descriptor +// +// val properties = item.allProperties() +// val bottom = Meta { +// VISIBLE_KEY put (item.visible ?: true) +// if (item is VisualObject3D) { +// MATERIAL_COLOR_KEY put "#ffffff" +// MATERIAL_OPACITY_KEY put 1.0 +// MATERIAL_WIREFRAME_KEY put false +// } +// } +// properties.withBottom(bottom) +// } } // canvas.clickListener = ::selectElement //tree.visualObjectTree(visual, editor::propertyEditor) - treeElement.displayObjectTree(visual) { name -> + treeElement.objectTree(visual) { name -> selectElement(name) canvas.highlight(name) } diff --git a/demo/muon-monitor/src/jsMain/web/css/jsoneditor.min.css b/demo/muon-monitor/src/jsMain/resources/css/jsoneditor.min.css similarity index 100% rename from demo/muon-monitor/src/jsMain/web/css/jsoneditor.min.css rename to demo/muon-monitor/src/jsMain/resources/css/jsoneditor.min.css diff --git a/demo/muon-monitor/src/jsMain/web/css/main.css b/demo/muon-monitor/src/jsMain/resources/css/main.css similarity index 100% rename from demo/muon-monitor/src/jsMain/web/css/main.css rename to demo/muon-monitor/src/jsMain/resources/css/main.css diff --git a/demo/muon-monitor/src/jsMain/web/img/jsoneditor-icons.svg b/demo/muon-monitor/src/jsMain/resources/img/jsoneditor-icons.svg similarity index 100% rename from demo/muon-monitor/src/jsMain/web/img/jsoneditor-icons.svg rename to demo/muon-monitor/src/jsMain/resources/img/jsoneditor-icons.svg diff --git a/demo/muon-monitor/src/jsMain/web/index.html b/demo/muon-monitor/src/jsMain/resources/index.html similarity index 100% rename from demo/muon-monitor/src/jsMain/web/index.html rename to demo/muon-monitor/src/jsMain/resources/index.html diff --git a/demo/muon-monitor/src/jvmMain/kotlin/ru/mipt/npm/muon/monitor/readResource.kt b/demo/muon-monitor/src/jvmMain/kotlin/ru/mipt/npm/muon/monitor/readResource.kt index 5cb275e1..4a12869f 100644 --- a/demo/muon-monitor/src/jvmMain/kotlin/ru/mipt/npm/muon/monitor/readResource.kt +++ b/demo/muon-monitor/src/jvmMain/kotlin/ru/mipt/npm/muon/monitor/readResource.kt @@ -1,7 +1,7 @@ package ru.mipt.npm.muon.monitor actual fun readResource(path: String): String { - return ClassLoader.getSystemClassLoader().getResourceAsStream(path)?.readAllBytes()?.decodeToString() + return ClassLoader.getSystemClassLoader().getResourceAsStream(path)?.readBytes()?.decodeToString() ?: error("Resource '$path' not found") } 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 f46f68e1..0cf95aa1 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 @@ -14,7 +14,7 @@ import io.ktor.http.content.static import io.ktor.response.respond import io.ktor.routing.Routing import io.ktor.routing.get -import io.ktor.serialization.serialization +import io.ktor.serialization.json import io.ktor.server.cio.CIO import io.ktor.server.engine.embeddedServer import org.apache.commons.math3.random.JDKRandomGenerator @@ -35,7 +35,7 @@ fun Application.module() { install(DefaultHeaders) install(CallLogging) install(ContentNegotiation) { - serialization(json = Visual3D.json) + json(module = Visual3D.serialModule) } install(Routing) { get("/event") { diff --git a/demo/muon-monitor/src/jvmTest/kotlin/ru/mipt/npm/muon/monitor/GeometryTest.kt b/demo/muon-monitor/src/jvmTest/kotlin/ru/mipt/npm/muon/monitor/GeometryTest.kt index 7c718e23..6e1ec106 100644 --- a/demo/muon-monitor/src/jvmTest/kotlin/ru/mipt/npm/muon/monitor/GeometryTest.kt +++ b/demo/muon-monitor/src/jvmTest/kotlin/ru/mipt/npm/muon/monitor/GeometryTest.kt @@ -1,7 +1,6 @@ package ru.mipt.npm.muon.monitor -import org.junit.Test -import kotlin.test.assertTrue +import kotlin.test.* class GeometryTest { diff --git a/demo/spatial-showcase/build.gradle.kts b/demo/spatial-showcase/build.gradle.kts index 46d63633..064f207d 100644 --- a/demo/spatial-showcase/build.gradle.kts +++ b/demo/spatial-showcase/build.gradle.kts @@ -1,25 +1,21 @@ -import org.openjfx.gradle.JavaFXOptions +import scientifik.DependencyConfiguration +import scientifik.FXModule +import scientifik.fx plugins { id("scientifik.mpp") - id("org.openjfx.javafxplugin") id("application") } +val fxVersion: String by rootProject.extra +fx(FXModule.CONTROLS, version = fxVersion, configuration = DependencyConfiguration.IMPLEMENTATION) + kotlin { jvm { withJava() } - js { - browser { - webpackTask { - sourceMaps = false - } - } - } - sourceSets { commonMain { dependencies { @@ -32,8 +28,4 @@ kotlin { application { mainClassName = "hep.dataforge.vis.spatial.demo.FXDemoAppKt" -} - -configure { - modules("javafx.controls") } \ No newline at end of file diff --git a/demo/spatial-showcase/src/commonMain/kotlin/hep/dataforge/vis/spatial/demo/demo.kt b/demo/spatial-showcase/src/commonMain/kotlin/hep/dataforge/vis/spatial/demo/demo.kt index ddb92491..836e6c2e 100644 --- a/demo/spatial-showcase/src/commonMain/kotlin/hep/dataforge/vis/spatial/demo/demo.kt +++ b/demo/spatial-showcase/src/commonMain/kotlin/hep/dataforge/vis/spatial/demo/demo.kt @@ -1,13 +1,13 @@ package hep.dataforge.vis.spatial.demo -import hep.dataforge.meta.buildMeta +import hep.dataforge.meta.Meta import hep.dataforge.meta.invoke import hep.dataforge.names.toName import hep.dataforge.output.OutputManager -import hep.dataforge.vis.common.Colors -import hep.dataforge.vis.common.VisualObject +import hep.dataforge.vis.Colors +import hep.dataforge.vis.VisualObject import hep.dataforge.vis.spatial.* -import hep.dataforge.vis.spatial.specifications.CanvasSpec +import hep.dataforge.vis.spatial.specifications.Canvas import kotlinx.coroutines.* import kotlin.math.PI import kotlin.math.cos @@ -16,14 +16,14 @@ import kotlin.random.Random fun OutputManager.demo(name: String, title: String = name, block: VisualGroup3D.() -> Unit) { - val meta = buildMeta { + val meta = Meta { "title" put title } val output = get(VisualObject::class, name.toName(), meta = meta) output.render(action = block) } -val canvasOptions = CanvasSpec { +val canvasOptions = Canvas { minSize = 500 axes { size = 500.0 @@ -31,7 +31,7 @@ val canvasOptions = CanvasSpec { } camera { distance = 600.0 - latitude = PI/6 + latitude = PI / 6 } } diff --git a/demo/spatial-showcase/src/jsMain/kotlin/hep/dataforge/vis/spatial/demo/ThreeDemoApp.kt b/demo/spatial-showcase/src/jsMain/kotlin/hep/dataforge/vis/spatial/demo/ThreeDemoApp.kt index 7d9adc3e..c773f7f7 100644 --- a/demo/spatial-showcase/src/jsMain/kotlin/hep/dataforge/vis/spatial/demo/ThreeDemoApp.kt +++ b/demo/spatial-showcase/src/jsMain/kotlin/hep/dataforge/vis/spatial/demo/ThreeDemoApp.kt @@ -2,16 +2,7 @@ package hep.dataforge.vis.spatial.demo 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.x -import hep.dataforge.vis.spatial.y -import kotlinx.coroutines.GlobalScope -import kotlinx.coroutines.delay -import kotlinx.coroutines.isActive -import kotlinx.coroutines.launch import kotlin.browser.document -import kotlin.random.Random private class ThreeDemoApp : Application { @@ -48,7 +39,6 @@ private class ThreeDemoApp : Application { } - override fun dispose() = emptyMap()//mapOf("lines" put presenter.dispose()) } fun main() { diff --git a/demo/spatial-showcase/src/jsMain/kotlin/hep/dataforge/vis/spatial/demo/ThreeDemoGrid.kt b/demo/spatial-showcase/src/jsMain/kotlin/hep/dataforge/vis/spatial/demo/ThreeDemoGrid.kt index 44a71b5a..e9f3cb8d 100644 --- a/demo/spatial-showcase/src/jsMain/kotlin/hep/dataforge/vis/spatial/demo/ThreeDemoGrid.kt +++ b/demo/spatial-showcase/src/jsMain/kotlin/hep/dataforge/vis/spatial/demo/ThreeDemoGrid.kt @@ -3,15 +3,11 @@ package hep.dataforge.vis.spatial.demo import hep.dataforge.context.Global import hep.dataforge.meta.Meta import hep.dataforge.meta.get -import hep.dataforge.meta.invoke import hep.dataforge.meta.string import hep.dataforge.names.Name import hep.dataforge.output.OutputManager import hep.dataforge.output.Renderer -import hep.dataforge.vis.common.VisualObject -import hep.dataforge.vis.spatial.specifications.AxesSpec -import hep.dataforge.vis.spatial.specifications.CameraSpec -import hep.dataforge.vis.spatial.specifications.CanvasSpec +import hep.dataforge.vis.VisualObject import hep.dataforge.vis.spatial.three.ThreeCanvas import hep.dataforge.vis.spatial.three.ThreePlugin import hep.dataforge.vis.spatial.three.output diff --git a/demo/spatial-showcase/src/jsMain/kotlin/hep/dataforge/vis/spatial/demo/VariableBox.kt b/demo/spatial-showcase/src/jsMain/kotlin/hep/dataforge/vis/spatial/demo/VariableBox.kt index 63e6c975..b18ca2aa 100644 --- a/demo/spatial-showcase/src/jsMain/kotlin/hep/dataforge/vis/spatial/demo/VariableBox.kt +++ b/demo/spatial-showcase/src/jsMain/kotlin/hep/dataforge/vis/spatial/demo/VariableBox.kt @@ -4,11 +4,12 @@ package hep.dataforge.vis.spatial.demo import hep.dataforge.meta.int import hep.dataforge.meta.number +import hep.dataforge.meta.setProperty import hep.dataforge.names.plus import hep.dataforge.names.startsWith -import hep.dataforge.vis.common.getProperty -import hep.dataforge.vis.common.set -import hep.dataforge.vis.common.setProperty +import hep.dataforge.values.asValue +import hep.dataforge.vis.getProperty +import hep.dataforge.vis.set import hep.dataforge.vis.spatial.* import hep.dataforge.vis.spatial.VisualObject3D.Companion.GEOMETRY_KEY import hep.dataforge.vis.spatial.demo.VariableBoxThreeFactory.Z_SIZE_KEY @@ -25,13 +26,13 @@ import kotlin.reflect.KClass internal var VisualObject3D.variableZSize: Number get() = getProperty(Z_SIZE_KEY, false).number ?: 0f set(value) { - setProperty(Z_SIZE_KEY, value) + setProperty(Z_SIZE_KEY, value.asValue()) } internal var VisualObject3D.value: Int get() = getProperty("value", false).int ?: 0 set(value) { - setProperty("value", value) + setProperty("value", value.asValue()) val size = value.toFloat() / 255f * 20f scaleZ = size z = -size / 2 diff --git a/demo/spatial-showcase/src/jsMain/web/index.html b/demo/spatial-showcase/src/jsMain/resources/index.html similarity index 100% rename from demo/spatial-showcase/src/jsMain/web/index.html rename to demo/spatial-showcase/src/jsMain/resources/index.html diff --git a/demo/spatial-showcase/src/jvmMain/kotlin/hep/dataforge/vis/spatial/demo/FXDemoGrid.kt b/demo/spatial-showcase/src/jvmMain/kotlin/hep/dataforge/vis/spatial/demo/FXDemoGrid.kt index 9357e5de..8211f4fd 100644 --- a/demo/spatial-showcase/src/jvmMain/kotlin/hep/dataforge/vis/spatial/demo/FXDemoGrid.kt +++ b/demo/spatial-showcase/src/jvmMain/kotlin/hep/dataforge/vis/spatial/demo/FXDemoGrid.kt @@ -6,11 +6,11 @@ import hep.dataforge.meta.buildMeta import hep.dataforge.names.Name import hep.dataforge.output.OutputManager import hep.dataforge.output.Renderer -import hep.dataforge.vis.common.VisualObject +import hep.dataforge.vis.VisualObject import hep.dataforge.vis.spatial.fx.FX3DPlugin import hep.dataforge.vis.spatial.fx.FXCanvas3D -import hep.dataforge.vis.spatial.specifications.AxesSpec -import hep.dataforge.vis.spatial.specifications.CanvasSpec +import hep.dataforge.vis.spatial.specifications.Axes as AxesSpec +import hep.dataforge.vis.spatial.specifications.Canvas as CanvasSpec import javafx.collections.FXCollections import javafx.scene.Parent import javafx.scene.control.Tab diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index cc4fdc29..490fda85 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 94920145..a4b44297 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.0.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-6.3-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew.bat b/gradlew.bat index 9618d8d9..62bd9b9c 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -29,6 +29,9 @@ if "%DIRNAME%" == "" set DIRNAME=. set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" diff --git a/playground/build.gradle.kts b/playground/build.gradle.kts new file mode 100644 index 00000000..3ad5ff15 --- /dev/null +++ b/playground/build.gradle.kts @@ -0,0 +1,27 @@ +plugins { + kotlin("multiplatform") +} + +repositories{ + jcenter() + 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/dev") +} + +kotlin { + js { + browser {} + } + + sourceSets { + commonMain { + dependencies { + api(project(":dataforge-vis-spatial")) + api(project(":dataforge-vis-spatial-gdml")) + } + } + } +} diff --git a/playground/src/jsMain/kotlin/PlayGroundApp.kt b/playground/src/jsMain/kotlin/PlayGroundApp.kt new file mode 100644 index 00000000..79efa165 --- /dev/null +++ b/playground/src/jsMain/kotlin/PlayGroundApp.kt @@ -0,0 +1,56 @@ +import hep.dataforge.context.Global +import hep.dataforge.js.Application +import hep.dataforge.js.startApplication +import hep.dataforge.names.Name +import hep.dataforge.vis.editor.objectTree +import hep.dataforge.vis.editor.visualPropertyEditor +import hep.dataforge.vis.spatial.Point3D +import hep.dataforge.vis.spatial.VisualGroup3D +import hep.dataforge.vis.spatial.box +import hep.dataforge.vis.spatial.group +import hep.dataforge.vis.spatial.three.ThreePlugin +import hep.dataforge.vis.spatial.three.threeCanvas +import org.w3c.dom.HTMLElement +import react.dom.div +import react.dom.render +import kotlin.browser.document + +private class PlayGroundApp : Application { + + private val three = Global.plugins.fetch(ThreePlugin) + + override fun start(state: Map) { + + val element = + document.getElementById("app") as? HTMLElement ?: error("Element with id 'canvas' not found on page") + + val obj = VisualGroup3D().apply { + box(100, 100, 100, name = "A") + group("B") { + position = Point3D(120, 0, 0) + box(100, 100, 100, name = "C") + } + } + + render(element) { + div("row") { + div("col-3") { + objectTree(obj) + } + div("col-6") { + threeCanvas(obj) + } + div("col-3") { + visualPropertyEditor(Name.EMPTY, obj) + } + } + } + + + } + +} + +fun main() { + startApplication(::PlayGroundApp) +} \ No newline at end of file diff --git a/playground/src/jsMain/resources/css/common.css b/playground/src/jsMain/resources/css/common.css new file mode 100644 index 00000000..4d1bac9d --- /dev/null +++ b/playground/src/jsMain/resources/css/common.css @@ -0,0 +1,40 @@ +/* Remove default bullets */ +ul, .objTree-subtree { + list-style-type: none; +} + +/* Style the caret/arrow */ +.objTree-caret { + cursor: pointer; + user-select: none; /* Prevent text selection */ +} + +/* Create the caret/arrow with a unicode, and style it */ +.objTree-caret::before { + content: "\25B6"; + color: black; + display: inline-block; + margin-right: 6px; +} + +/* Rotate the caret/arrow icon when clicked on (using JavaScript) */ +.objTree-caret-down::before { + transform: rotate(90deg); +} + +ul, .tree { + list-style-type: none; +} + +i, .tree-caret{ + display: inline-block; + margin-right: 6px; +} + +.rotate { + transform: rotate(90deg); +} + +.tree-label-inactive { + color: gray; +} diff --git a/playground/src/jsMain/resources/index.html b/playground/src/jsMain/resources/index.html new file mode 100644 index 00000000..c022a175 --- /dev/null +++ b/playground/src/jsMain/resources/index.html @@ -0,0 +1,16 @@ + + + + + Playground + + + + + +
+

Playground

+
+
+ + \ No newline at end of file diff --git a/settings.gradle.kts b/settings.gradle.kts index 7dbf2794..b6673c37 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -13,7 +13,6 @@ pluginManagement { resolutionStrategy { eachPlugin { when (requested.id.id) { - "kotlin-dce-js" -> useModule("org.jetbrains.kotlin:kotlin-gradle-plugin:${requested.version}") "scientifik.mpp", "scientifik.publish", "scientifik.jvm", "scientifik.js" -> useModule("scientifik:gradle-tools:${requested.version}") "org.openjfx.javafxplugin" -> useModule("org.openjfx:javafx-plugin:${requested.version}") } @@ -27,12 +26,12 @@ rootProject.name = "dataforge-vis" include( ":dataforge-vis-common", -// ":wrappers", ":dataforge-vis-spatial", ":dataforge-vis-spatial-gdml", ":demo:spatial-showcase", ":demo:gdml", - ":demo:muon-monitor" + ":demo:muon-monitor", + ":playground" ) //if(file("../dataforge-core").exists()) {