Merge pull request #24 from mipt-npm/dev

Dev
This commit is contained in:
Alexander Nozik 2020-04-12 19:31:02 +03:00 committed by GitHub
commit 9567f7db93
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
124 changed files with 7471 additions and 823 deletions

View File

@ -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 { plugins {
val kotlinVersion = "1.3.61" val toolsVersion = "0.4.2"
val toolsVersion = "0.3.2"
kotlin("jvm") version kotlinVersion apply false
id("kotlin-dce-js") version kotlinVersion apply false
id("scientifik.mpp") version toolsVersion apply false id("scientifik.mpp") version toolsVersion apply false
id("scientifik.jvm") version toolsVersion apply false id("scientifik.jvm") version toolsVersion apply false
id("scientifik.js") version toolsVersion apply false id("scientifik.js") version toolsVersion apply false
@ -21,21 +18,23 @@ allprojects {
maven("https://dl.bintray.com/pdvrieze/maven") maven("https://dl.bintray.com/pdvrieze/maven")
maven("http://maven.jzy3d.org/releases") maven("http://maven.jzy3d.org/releases")
maven("https://kotlin.bintray.com/js-externals") 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/gbaldeck/kotlin")
// maven("https://dl.bintray.com/rjaros/kotlin") // maven("https://dl.bintray.com/rjaros/kotlin")
} }
group = "hep.dataforge" group = "hep.dataforge"
version = "0.1.1" version = "0.1.3-dev"
}
subprojects{
this.useSerialization()
} }
val githubProject by extra("dataforge-vis") val githubProject by extra("dataforge-vis")
val bintrayRepo by extra("dataforge") val bintrayRepo by extra("dataforge")
val fxVersion by extra("14")
subprojects { subprojects {
apply(plugin = "scientifik.publish") apply(plugin = "scientifik.publish")
serialization()
afterEvaluate {
fx(scientifik.FXModule.CONTROLS, version = fxVersion)
}
} }

View File

@ -1,50 +1,49 @@
import org.openjfx.gradle.JavaFXOptions
import scientifik.useSerialization
plugins { plugins {
id("scientifik.mpp") id("scientifik.mpp")
id("org.openjfx.javafxplugin")
} }
val dataforgeVersion: String by rootProject.extra val dataforgeVersion: String by rootProject.extra
//val kvisionVersion: String by rootProject.extra("2.0.0-M1") //val kvisionVersion: String by rootProject.extra("2.0.0-M1")
useSerialization()
kotlin { kotlin {
jvm{
withJava()
}
sourceSets { sourceSets {
commonMain{ commonMain {
dependencies { dependencies {
api("hep.dataforge:dataforge-output:$dataforgeVersion") api("hep.dataforge:dataforge-output:$dataforgeVersion")
} }
} }
jvmMain{ jvmMain {
dependencies { dependencies {
api("no.tornado:tornadofx:1.7.19") api("no.tornado:tornadofx:1.7.20")
//api("no.tornado:tornadofx-controlsfx:0.1.1") //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") exclude(group = "org.openjfx")
} }
api("de.jensd:fontawesomefx-commons:11.0"){ api("de.jensd:fontawesomefx-commons:11.0") {
exclude(group = "org.openjfx") exclude(group = "org.openjfx")
} }
} }
} }
jsMain{ jsMain {
dependencies { dependencies {
api("hep.dataforge:dataforge-output-html:$dataforgeVersion") api("hep.dataforge:dataforge-output-html:$dataforgeVersion")
//api(npm("bootstrap","4.4.1"))
implementation(npm("jsoneditor")) //React, React DOM + Wrappers (chapter 3)
implementation(npm("file-saver")) 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<JavaFXOptions> {
modules("javafx.controls")
}

View File

@ -1,4 +1,4 @@
package hep.dataforge.vis.common package hep.dataforge.vis
import hep.dataforge.meta.MetaItem import hep.dataforge.meta.MetaItem
import hep.dataforge.names.Name import hep.dataforge.names.Name
@ -20,6 +20,17 @@ abstract class AbstractVisualGroup : AbstractVisualObject(), MutableVisualGroup
*/ */
abstract override val children: Map<NameToken, VisualObject> abstract override val children: Map<NameToken, VisualObject>
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<*>?) { override fun propertyChanged(name: Name, before: MetaItem<*>?, after: MetaItem<*>?) {
super.propertyChanged(name, before, after) super.propertyChanged(name, before, after)
forEach { forEach {
@ -37,7 +48,12 @@ abstract class AbstractVisualGroup : AbstractVisualObject(), MutableVisualGroup
* Add listener for children change * Add listener for children change
*/ */
override fun onChildrenChange(owner: Any?, action: (Name, VisualObject?) -> Unit) { 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 * Add a static child. Statics could not be found by name, removed or replaced
*/ */
protected open fun addStatic(child: VisualObject) = 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 * 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 * 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) { if (child == null) {
removeChild(token) removeChild(token)
} else { } else {
attach(child)
setChild(token, child) setChild(token, child)
} }
} }
else -> { else -> {
//TODO add safety check //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 parent[name.last()!!.asName()] = child
} }
} }
structureChangeListeners.forEach { it.callback(name, child) } childrenChanged(name, child)
} }
} }

View File

@ -1,9 +1,10 @@
package hep.dataforge.vis.common package hep.dataforge.vis
import hep.dataforge.meta.* import hep.dataforge.meta.*
import hep.dataforge.names.Name import hep.dataforge.names.Name
import hep.dataforge.names.asName 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 import kotlinx.serialization.Transient
internal data class PropertyListener( internal data class PropertyListener(
@ -14,7 +15,7 @@ internal data class PropertyListener(
abstract class AbstractVisualObject : VisualObject { abstract class AbstractVisualObject : VisualObject {
@Transient @Transient
override var parent: VisualObject? = null override var parent: VisualGroup? = null
protected abstract var properties: Config? protected abstract var properties: Config?
@ -22,7 +23,7 @@ abstract class AbstractVisualObject : VisualObject {
get() = properties?.get(STYLE_KEY).stringList get() = properties?.get(STYLE_KEY).stringList
set(value) { set(value) {
//val allStyles = (field + value).distinct() //val allStyles = (field + value).distinct()
setProperty(STYLE_KEY, value) setProperty(STYLE_KEY, Value.of(value))
updateStyles(value) updateStyles(value)
} }
@ -66,7 +67,7 @@ abstract class AbstractVisualObject : VisualObject {
private var styleCache: Meta? = null 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 protected val mergedStyles: Meta
get() = styleCache ?: findAllStyles().merge().also { get() = styleCache ?: findAllStyles().merge().also {

View File

@ -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.ValueType
import hep.dataforge.values.int import hep.dataforge.values.int
import kotlin.math.max import kotlin.math.max
@ -234,7 +237,7 @@ object Colors {
/** /**
* Convert three bytes representing color to Meta * 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() RED_KEY put r.toInt()
GREEN_KEY put g.toInt() GREEN_KEY put g.toInt()
BLUE_KEY put b.toInt() BLUE_KEY put b.toInt()

View File

@ -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<NameToken, VisualObject>()
override val children: Map<NameToken, VisualObject> 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()
}

View File

@ -1,18 +1,19 @@
@file:UseSerializers(MetaSerializer::class) @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.meta.*
import hep.dataforge.names.Name import hep.dataforge.names.Name
import hep.dataforge.names.asName import hep.dataforge.names.asName
import kotlinx.serialization.* import kotlinx.serialization.*
import kotlinx.serialization.builtins.MapSerializer
import kotlinx.serialization.builtins.serializer
/** /**
* A container for styles * A container for styles
*/ */
@Serializable @Serializable
class StyleSheet() { class StyleSheet private constructor(private val styleMap: MutableMap<String, Meta> = LinkedHashMap()) {
@Transient @Transient
internal var owner: VisualObject? = null internal var owner: VisualObject? = null
@ -20,12 +21,10 @@ class StyleSheet() {
this.owner = owner this.owner = owner
} }
private val styleMap = HashMap<String, Meta>()
val items: Map<String, Meta> get() = styleMap val items: Map<String, Meta> get() = styleMap
operator fun get(key: String): Meta? { 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) { 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()) set(key, newStyle.seal())
} }
companion object: KSerializer<StyleSheet>{ @Serializer(StyleSheet::class)
override val descriptor: SerialDescriptor companion object : KSerializer<StyleSheet> {
get() = TODO("Not yet implemented") private val mapSerializer = MapSerializer(String.serializer(), MetaSerializer)
override val descriptor: SerialDescriptor get() = mapSerializer.descriptor
override fun deserialize(decoder: Decoder): StyleSheet { override fun deserialize(decoder: Decoder): StyleSheet {
TODO("Not yet implemented") val map = mapSerializer.deserialize(decoder)
return StyleSheet(map as? MutableMap<String, Meta> ?: LinkedHashMap(map))
} }
override fun serialize(encoder: Encoder, obj: StyleSheet) { override fun serialize(encoder: Encoder, value: StyleSheet) {
TODO("Not yet implemented") mapSerializer.serialize(encoder, value.items)
} }
} }

View File

@ -1,4 +1,4 @@
package hep.dataforge.vis.common package hep.dataforge.vis
import hep.dataforge.context.* import hep.dataforge.context.*
import hep.dataforge.meta.Meta 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 tag: PluginTag = PluginTag(name = "visual", group = PluginTag.DATAFORGE_GROUP)
override val type: KClass<out Visual> = Visual::class override val type: KClass<out Visual> = 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" const val VISUAL_FACTORY_TYPE = "visual.factory"
} }

View File

@ -1,4 +1,4 @@
package hep.dataforge.vis.common package hep.dataforge.vis
import hep.dataforge.names.* import hep.dataforge.names.*
import hep.dataforge.provider.Provider import hep.dataforge.provider.Provider
@ -6,7 +6,8 @@ import hep.dataforge.provider.Provider
/** /**
* Represents a group of [VisualObject] instances * Represents a group of [VisualObject] instances
*/ */
interface VisualGroup : Provider, Iterable<VisualObject>, VisualObject { interface VisualGroup : Provider, Iterable<VisualObject>,
VisualObject {
/** /**
* A map of top level named children * A map of top level named children
*/ */

View File

@ -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.Name
import hep.dataforge.names.asName import hep.dataforge.names.asName
import hep.dataforge.names.toName import hep.dataforge.names.toName
import hep.dataforge.provider.Type 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 import kotlinx.serialization.Transient
//private fun Laminate.withTop(meta: Meta): Laminate = Laminate(listOf(meta) + layers) //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. * The parent object of this one. If null, this one is a root.
*/ */
@Transient @Transient
var parent: VisualObject? var parent: VisualGroup?
/** /**
* All properties including styles and prototypes if present, but without inheritance * All properties including styles and prototypes if present, but without inheritance
*/ */
fun allProperties(): Laminate fun allProperties(): Laminate
/**
* Set property for this object
*/
fun setProperty(name: Name, value: Any?) {
config[name] = value
}
/** /**
* Get property including or excluding parent properties * 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 * 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" const val TYPE = "visual"
val STYLE_KEY = "@style".asName() 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 META_KEY = "@meta"
//const val TAGS_KEY = "@tags" //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) 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. * Add style name to the list of styles to be resolved later. The style with given name does not necessary exist at the moment.
*/ */

View File

@ -1,4 +1,4 @@
package hep.dataforge.vis.common package hep.dataforge.vis
import hep.dataforge.meta.* import hep.dataforge.meta.*
import hep.dataforge.names.Name import hep.dataforge.names.Name
@ -105,8 +105,8 @@ fun VisualObject.int(default: Int, name: Name? = null, inherited: Boolean = fals
inline fun <reified E : Enum<E>> VisualObject.enum(default: E, name: Name? = null, inherited: Boolean = false) = inline fun <reified E : Enum<E>> VisualObject.enum(default: E, name: Name? = null, inherited: Boolean = false) =
VisualObjectDelegateWrapper(this, name, default, inherited) { VisualObjectDelegateWrapper(this, name, default, inherited) { item ->
item -> item.string?.let { enumValueOf<E>(it) } item.string?.let { enumValueOf<E>(it) }
} }
//merge properties //merge properties

View File

@ -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
}

View File

@ -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())
}

View File

@ -0,0 +1,17 @@
package hep.dataforge.js
import react.RComponent
import kotlin.properties.ReadWriteProperty
import kotlin.reflect.KProperty
fun <T> RComponent<*, *>.initState(init: () -> T): ReadWriteProperty<RComponent<*, *>, T> =
object : ReadWriteProperty<RComponent<*, *>, 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)
}
}

View File

@ -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<ConfigEditorProps, TreeState>() {
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<NameToken> {
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
}
}
}

View File

@ -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<MetaViewerProps, TreeState>() {
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()
}
}
}
}
}
}
}
}
}
}
}

View File

@ -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<ObjectTreeProps, TreeState>() {
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)
}
}

View File

@ -1,8 +1,12 @@
package hep.dataforge.vis.js.editor package hep.dataforge.vis.editor
import kotlinx.html.* import kotlinx.html.*
import kotlinx.html.js.div import kotlinx.html.js.div
import org.w3c.dom.HTMLElement import org.w3c.dom.HTMLElement
import react.RBuilder
import react.ReactElement
import react.dom.div
import react.dom.h3
inline fun TagConsumer<HTMLElement>.card(title: String, crossinline block: TagConsumer<HTMLElement>.() -> Unit) { inline fun TagConsumer<HTMLElement>.card(title: String, crossinline block: TagConsumer<HTMLElement>.() -> Unit) {
div("card w-100") { div("card w-100") {
@ -13,6 +17,14 @@ inline fun TagConsumer<HTMLElement>.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<HTMLElement>.accordion(id: String, elements: Map<String, DIV.() -> Unit>) { fun TagConsumer<HTMLElement>.accordion(id: String, elements: Map<String, DIV.() -> Unit>) {
div("container-fluid") { div("container-fluid") {
div("accordion") { div("accordion") {

View File

@ -1,10 +1,10 @@
package hep.dataforge.vis.js.editor package hep.dataforge.vis.editor
import hep.dataforge.names.Name import hep.dataforge.names.Name
import hep.dataforge.names.plus import hep.dataforge.names.plus
import hep.dataforge.vis.common.VisualGroup import hep.dataforge.vis.VisualGroup
import hep.dataforge.vis.common.VisualObject import hep.dataforge.vis.VisualObject
import hep.dataforge.vis.common.isEmpty import hep.dataforge.vis.isEmpty
import kotlinx.html.TagConsumer import kotlinx.html.TagConsumer
import kotlinx.html.dom.append import kotlinx.html.dom.append
import kotlinx.html.js.* import kotlinx.html.js.*
@ -13,18 +13,18 @@ import org.w3c.dom.HTMLElement
import org.w3c.dom.HTMLSpanElement import org.w3c.dom.HTMLSpanElement
import kotlin.dom.clear import kotlin.dom.clear
fun Element.displayObjectTree( //fun Element.displayObjectTree(
obj: VisualObject, // obj: VisualObject,
clickCallback: (Name) -> Unit = {} // clickCallback: (Name) -> Unit = {}
) { //) {
clear() // clear()
append { // append {
card("Object tree") { // card("Object tree") {
subTree(Name.EMPTY, obj, clickCallback) // subTree(Name.EMPTY, obj, clickCallback)
} // }
} // }
} //}
//
private fun TagConsumer<HTMLElement>.subTree( private fun TagConsumer<HTMLElement>.subTree(
name: Name, name: Name,
obj: VisualObject, obj: VisualObject,

View File

@ -6,7 +6,7 @@
"EXTERNAL_DELEGATION" "EXTERNAL_DELEGATION"
) )
package hep.dataforge.vis.js.editor package hep.dataforge.vis.editor
import org.w3c.dom.HTMLElement import org.w3c.dom.HTMLElement

View File

@ -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<dynamic>(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)
}

View File

@ -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<dynamic>(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()
)
}
}
}
}
}
}
}

View File

@ -21,3 +21,20 @@ ul, .objTree-subtree {
.objTree-caret-down::before { .objTree-caret-down::before {
transform: rotate(90deg); 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;
}

View File

@ -1,7 +1,6 @@
package hep.dataforge.vis.fx package hep.dataforge.vis
import hep.dataforge.context.* import hep.dataforge.context.*
import hep.dataforge.meta.EmptyMeta
import hep.dataforge.meta.Meta import hep.dataforge.meta.Meta
import hep.dataforge.meta.boolean import hep.dataforge.meta.boolean
import javafx.application.Application import javafx.application.Application
@ -20,7 +19,7 @@ import kotlin.reflect.KClass
/** /**
* Plugin holding JavaFX application instance and its root stage * 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 override val tag: PluginTag get() = Companion.tag
private val stages: ObservableSet<Stage> = FXCollections.observableSet() private val stages: ObservableSet<Stage> = FXCollections.observableSet()
@ -96,7 +95,8 @@ class FXPlugin(meta: Meta = EmptyMeta) : AbstractPlugin(meta) {
companion object : PluginFactory<FXPlugin> { companion object : PluginFactory<FXPlugin> {
override val type: KClass<out FXPlugin> = FXPlugin::class override val type: KClass<out FXPlugin> = FXPlugin::class
override val tag: PluginTag = PluginTag("vis.fx", group = PluginTag.DATAFORGE_GROUP) 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)
} }
} }

View File

@ -1,4 +1,4 @@
package hep.dataforge.vis.fx.editor package hep.dataforge.vis.editor
import hep.dataforge.meta.Meta import hep.dataforge.meta.Meta
import hep.dataforge.names.Name import hep.dataforge.names.Name

View File

@ -3,7 +3,7 @@
* To change this template file, choose Tools | Templates * To change this template file, choose Tools | Templates
* and open the template in the editor. * 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.Meta
import hep.dataforge.meta.get import hep.dataforge.meta.get

View File

@ -3,15 +3,15 @@
* To change this template file, choose Tools | Templates * To change this template file, choose Tools | Templates
* and open the template in the editor. * 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.FontAwesomeIcon
import de.jensd.fx.glyphs.fontawesome.FontAwesomeIconView import de.jensd.fx.glyphs.fontawesome.FontAwesomeIconView
import hep.dataforge.context.Global import hep.dataforge.context.Global
import hep.dataforge.descriptors.NodeDescriptor
import hep.dataforge.meta.Config import hep.dataforge.meta.Config
import hep.dataforge.meta.descriptors.NodeDescriptor
import hep.dataforge.names.NameToken import hep.dataforge.names.NameToken
import hep.dataforge.vis.fx.dfIconView import hep.dataforge.vis.dfIconView
import javafx.scene.Node import javafx.scene.Node
import javafx.scene.control.* import javafx.scene.control.*
import javafx.scene.control.cell.TextFieldTreeTableCell import javafx.scene.control.cell.TextFieldTreeTableCell
@ -128,7 +128,11 @@ class ConfigEditor(
when (item) { when (item) {
is FXMetaValue<Config> -> { is FXMetaValue<Config> -> {
text = null text = null
val chooser = ValueChooser.build(Global, item.valueProperty, item.descriptor) { val chooser = ValueChooser.build(
Global,
item.valueProperty,
item.descriptor
) {
item.set(it) item.set(it)
} }
graphic = chooser.node graphic = chooser.node

View File

@ -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.*
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.Name
import hep.dataforge.names.NameToken import hep.dataforge.names.NameToken
import hep.dataforge.names.asName import hep.dataforge.names.asName
@ -174,10 +174,10 @@ private fun <M : MutableMeta<M>> M.createEmptyNode(token: NameToken, append: Boo
val name = token.asName() val name = token.asName()
val index = (getIndexed(name).keys.mapNotNull { it.toIntOrNull() }.max() ?: -1) + 1 val index = (getIndexed(name).keys.mapNotNull { it.toIntOrNull() }.max() ?: -1) + 1
val newName = name.withIndex(index.toString()) val newName = name.withIndex(index.toString())
set(newName, EmptyMeta) set(newName, Meta.EMPTY)
get(newName).node!! get(newName).node!!
} else { } else {
this.setNode(token.asName(), EmptyMeta) this.setNode(token.asName(), Meta.EMPTY)
//FIXME possible concurrency bug //FIXME possible concurrency bug
get(token).node!! get(token).node!!
} }
@ -211,9 +211,9 @@ fun <M : MutableMeta<M>> FXMetaNode<M>.addValue(key: String) {
fun <M : MutableMeta<M>> FXMetaNode<M>.addNode(key: String) { fun <M : MutableMeta<M>> FXMetaNode<M>.addNode(key: String) {
val parent = getOrCreateNode() val parent = getOrCreateNode()
if (descriptor?.multiple == true) { if (descriptor?.multiple == true) {
parent.append(key, EmptyMeta) parent.append(key, Meta.EMPTY)
} else { } else {
parent[key] = EmptyMeta parent[key] = Meta.EMPTY
} }
} }

View File

@ -14,18 +14,23 @@
* limitations under the License. * limitations under the License.
*/ */
package hep.dataforge.vis.fx.editor package hep.dataforge.vis.editor
import hep.dataforge.meta.Meta import hep.dataforge.meta.Meta
import hep.dataforge.vis.fx.dfIconView import hep.dataforge.vis.dfIconView
import javafx.beans.property.SimpleStringProperty import javafx.beans.property.SimpleStringProperty
import javafx.scene.control.TreeItem import javafx.scene.control.TreeItem
import javafx.scene.control.TreeSortMode import javafx.scene.control.TreeSortMode
import javafx.scene.control.TreeTableView import javafx.scene.control.TreeTableView
import tornadofx.* import tornadofx.*
class MetaViewer(val rootNode: FXMetaNode<*>, title: String = "Meta viewer") : Fragment(title, dfIconView) { class MetaViewer(val rootNode: FXMetaNode<*>, title: String = "Meta viewer") : Fragment(title,
constructor(meta: Meta, title: String = "Meta viewer"): this(FXMeta.root(meta),title = title) dfIconView
) {
constructor(meta: Meta, title: String = "Meta viewer"): this(
FXMeta.root(
meta
),title = title)
override val root = borderpane { override val root = borderpane {
center { center {

View File

@ -3,7 +3,7 @@
* To change this template file, choose Tools | Templates * To change this template file, choose Tools | Templates
* and open the template in the editor. * 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.Meta
import hep.dataforge.names.Name import hep.dataforge.names.Name

View File

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

View File

@ -3,20 +3,19 @@
* To change this template file, choose Tools | Templates * To change this template file, choose Tools | Templates
* and open the template in the editor. * 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.Context
import hep.dataforge.context.Named import hep.dataforge.context.Named
import hep.dataforge.descriptors.ValueDescriptor
import hep.dataforge.meta.EmptyMeta
import hep.dataforge.meta.Meta import hep.dataforge.meta.Meta
import hep.dataforge.meta.descriptors.ValueDescriptor
import hep.dataforge.names.toName import hep.dataforge.names.toName
import hep.dataforge.provider.Type import hep.dataforge.provider.Type
import hep.dataforge.provider.provideByType import hep.dataforge.provider.provideByType
import hep.dataforge.values.Null import hep.dataforge.values.Null
import hep.dataforge.values.Value import hep.dataforge.values.Value
import hep.dataforge.vis.common.widget import hep.dataforge.vis.widget
import hep.dataforge.vis.common.widgetType import hep.dataforge.vis.widgetType
import javafx.beans.property.ObjectProperty import javafx.beans.property.ObjectProperty
import javafx.beans.value.ObservableValue import javafx.beans.value.ObservableValue
import javafx.scene.Node import javafx.scene.Node
@ -66,7 +65,7 @@ interface ValueChooser {
@Type("hep.dataforge.vis.fx.valueChooserFactory") @Type("hep.dataforge.vis.fx.valueChooserFactory")
interface Factory : Named { interface Factory : Named {
operator fun invoke(meta: Meta = EmptyMeta): ValueChooser operator fun invoke(meta: Meta = Meta.EMPTY): ValueChooser
} }
companion object { companion object {
@ -108,8 +107,7 @@ interface ValueChooser {
descriptor: ValueDescriptor? = null, descriptor: ValueDescriptor? = null,
setter: (Value) -> Unit setter: (Value) -> Unit
): ValueChooser { ): ValueChooser {
val chooser = val chooser = build(context, descriptor)
build(context, descriptor)
chooser.setDisplayValue(value.value ?: Null) chooser.setDisplayValue(value.value ?: Null)
value.onChange { value.onChange {
chooser.setDisplayValue(it ?: Null) chooser.setDisplayValue(it ?: Null)

View File

@ -3,9 +3,9 @@
* To change this template file, choose Tools | Templates * To change this template file, choose Tools | Templates
* and open the template in the editor. * 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.Null
import hep.dataforge.values.Value import hep.dataforge.values.Value
import javafx.beans.property.SimpleObjectProperty import javafx.beans.property.SimpleObjectProperty

View File

@ -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.Config
import hep.dataforge.meta.Meta import hep.dataforge.meta.Meta
import hep.dataforge.meta.descriptors.NodeDescriptor
import hep.dataforge.meta.update import hep.dataforge.meta.update
import hep.dataforge.vis.common.VisualObject import hep.dataforge.vis.VisualObject
import hep.dataforge.vis.common.findStyle import hep.dataforge.vis.findStyle
import javafx.beans.binding.Binding import javafx.beans.binding.Binding
import javafx.beans.property.SimpleObjectProperty import javafx.beans.property.SimpleObjectProperty
import javafx.scene.Node import javafx.scene.Node

View File

@ -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.VisualGroup
import hep.dataforge.vis.common.VisualObject import hep.dataforge.vis.VisualObject
import javafx.beans.property.SimpleObjectProperty import javafx.beans.property.SimpleObjectProperty
import javafx.scene.control.SelectionMode import javafx.scene.control.SelectionMode
import javafx.scene.control.TreeItem import javafx.scene.control.TreeItem

View File

@ -1,12 +1,12 @@
package hep.dataforge.vis.fx.demo package hep.dataforge.vis.demo
import hep.dataforge.descriptors.NodeDescriptor import hep.dataforge.meta.Meta
import hep.dataforge.meta.buildMeta import hep.dataforge.meta.asConfig
import hep.dataforge.meta.toConfig import hep.dataforge.meta.descriptors.NodeDescriptor
import hep.dataforge.values.ValueType import hep.dataforge.values.ValueType
import hep.dataforge.vis.fx.editor.ConfigEditor import hep.dataforge.vis.editor.ConfigEditor
import hep.dataforge.vis.fx.editor.FXMeta import hep.dataforge.vis.editor.FXMeta
import hep.dataforge.vis.fx.editor.MetaViewer import hep.dataforge.vis.editor.MetaViewer
import javafx.geometry.Orientation import javafx.geometry.Orientation
import tornadofx.* import tornadofx.*
@ -15,7 +15,7 @@ class MetaEditorDemoApp : App(MetaEditorDemo::class)
class MetaEditorDemo : View("Meta editor demo") { class MetaEditorDemo : View("Meta editor demo") {
val meta = buildMeta { val meta = Meta {
"aNode" put { "aNode" put {
"innerNode" put { "innerNode" put {
"innerValue" put true "innerValue" put true
@ -23,33 +23,35 @@ class MetaEditorDemo : View("Meta editor demo") {
"b" put 223 "b" put 223
"c" put "StringValue" "c" put "StringValue"
} }
}.toConfig() }.asConfig()
val descriptor = NodeDescriptor { val descriptor = NodeDescriptor {
node("aNode") { defineNode("aNode") {
info = "A root demo node" info = "A root demo node"
value("b") { defineValue("b") {
info = "b number value" info = "b number value"
type(ValueType.NUMBER) type(ValueType.NUMBER)
} }
node("otherNode") { defineNode("otherNode") {
value("otherValue") { defineValue("otherValue") {
type(ValueType.BOOLEAN) type(ValueType.BOOLEAN)
default(false) default(false)
info = "default value" info = "default value"
} }
} }
} }
value("multiple"){ defineValue("multiple") {
info = "A sns value" info = "A sns value"
multiple = true multiple = true
} }
} }
private val rootNode = FXMeta.root(meta,descriptor) private val rootNode = FXMeta.root(meta, descriptor)
override val root = override val root =
splitpane(Orientation.HORIZONTAL, MetaViewer(rootNode).root, ConfigEditor(rootNode).root) splitpane(Orientation.HORIZONTAL, MetaViewer(rootNode).root, ConfigEditor(
rootNode
).root)
} }
fun main() { fun main() {

View File

@ -7,7 +7,7 @@ kotlin {
val commonMain by getting { val commonMain by getting {
dependencies { dependencies {
api(project(":dataforge-vis-spatial")) api(project(":dataforge-vis-spatial"))
api("scientifik:gdml:0.1.6") api("scientifik:gdml:0.1.7")
} }
} }
} }

View File

@ -2,12 +2,12 @@ package hep.dataforge.vis.spatial.gdml
import hep.dataforge.meta.Meta import hep.dataforge.meta.Meta
import hep.dataforge.meta.MetaBuilder import hep.dataforge.meta.MetaBuilder
import hep.dataforge.meta.buildMeta
import hep.dataforge.names.Name import hep.dataforge.names.Name
import hep.dataforge.names.asName
import hep.dataforge.names.toName import hep.dataforge.names.toName
import hep.dataforge.vis.common.useStyle
import hep.dataforge.vis.spatial.* import hep.dataforge.vis.spatial.*
import hep.dataforge.vis.spatial.Material3D.Companion.MATERIAL_COLOR_KEY import hep.dataforge.vis.spatial.Material3D.Companion.MATERIAL_COLOR_KEY
import hep.dataforge.vis.useStyle
import scientifik.gdml.* import scientifik.gdml.*
import kotlin.random.Random import kotlin.random.Random
@ -44,7 +44,7 @@ class GDMLTransformer(val root: GDML) {
fun VisualObject3D.useStyle(name: String, builder: MetaBuilder.() -> Unit) { fun VisualObject3D.useStyle(name: String, builder: MetaBuilder.() -> Unit) {
styleCache.getOrPut(name.toName()) { styleCache.getOrPut(name.toName()) {
buildMeta(builder) Meta(builder)
} }
useStyle(name) useStyle(name)
} }
@ -69,7 +69,13 @@ class GDMLTransformer(val root: GDML) {
var onFinish: GDMLTransformer.() -> Unit = {} var onFinish: GDMLTransformer.() -> Unit = {}
internal fun finalize(final: VisualGroup3D): VisualGroup3D { 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 { styleCache.forEach {
final.styleSheet { final.styleSheet {
define(it.key.toString(), it.value) define(it.key.toString(), it.value)

View File

@ -4,8 +4,8 @@ package hep.dataforge.vis.spatial.gdml
import hep.dataforge.names.Name import hep.dataforge.names.Name
import hep.dataforge.names.asName import hep.dataforge.names.asName
import hep.dataforge.names.plus import hep.dataforge.names.plus
import hep.dataforge.vis.common.get import hep.dataforge.vis.get
import hep.dataforge.vis.common.set import hep.dataforge.vis.set
import hep.dataforge.vis.spatial.* import hep.dataforge.vis.spatial.*
import hep.dataforge.vis.spatial.World.ONE import hep.dataforge.vis.spatial.World.ONE
import hep.dataforge.vis.spatial.World.ZERO import hep.dataforge.vis.spatial.World.ZERO

View File

@ -1,43 +1,29 @@
package hep.dataforge.vis.spatial.gdml package hep.dataforge.vis.spatial.gdml
import hep.dataforge.vis.spatial.stringify
import nl.adaptivity.xmlutil.StAXReader import nl.adaptivity.xmlutil.StAXReader
import org.junit.Test import org.junit.jupiter.api.Test
import scientifik.gdml.GDML import scientifik.gdml.GDML
import java.io.File
import java.net.URL
import kotlin.test.Ignore
class TestConvertor { class TestConvertor {
@Test @Test
@Ignore
fun testBMNGeometry() { fun testBMNGeometry() {
val url = URL("https://drive.google.com/open?id=1w5e7fILMN83JGgB8WANJUYm8OW2s0WVO") val stream = javaClass.getResourceAsStream("/gdml/BM@N.gdml")
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 xmlReader = StAXReader(stream, "UTF-8") val xmlReader = StAXReader(stream, "UTF-8")
val xml = GDML.format.parse(GDML.serializer(), xmlReader) val xml = GDML.format.parse(GDML.serializer(), xmlReader)
val visual = xml.toVisual() 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)
} }
} }

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,254 @@
<gdml>
<define>
<position name="center" x="0.0" y="0.0" z="0.0" unit="cm"/>
<position name="box_position" x="25.0" y="50.0" z="75.0" unit="cm"/>
<rotation name="Rot0" x="0.0" y="0.0" z="0.0" unit="deg"/>
<rotation name="Rot1" x="0.0" y="0.0" z="60.0" unit="deg"/>
<rotation name="Rot2" x="0.0" y="0.0" z="120.0" unit="deg"/>
<rotation name="Rot3" x="0.0" y="0.0" z="180.0" unit="deg"/>
<rotation name="Rot4" x="0.0" y="0.0" z="240.0" unit="deg"/>
<rotation name="Rot5" x="0.0" y="0.0" z="300.0" unit="deg"/>
<rotation name="Rot000" x="0.0" y="0.0" z="0.0" unit="deg"/>
<position name="Pos000" x="-50.0" y="-50.0" z="-50.0" unit="cm"/>
<rotation name="Rot001" x="0.0" y="0.0" z="120.0" unit="deg"/>
<position name="Pos001" x="-50.0" y="-50.0" z="0.0" unit="cm"/>
<rotation name="Rot002" x="0.0" y="0.0" z="240.0" unit="deg"/>
<position name="Pos002" x="-50.0" y="-50.0" z="50.0" unit="cm"/>
<rotation name="Rot010" x="0.0" y="120.0" z="0.0" unit="deg"/>
<position name="Pos010" x="-50.0" y="0.0" z="-50.0" unit="cm"/>
<rotation name="Rot011" x="0.0" y="120.0" z="120.0" unit="deg"/>
<position name="Pos011" x="-50.0" y="0.0" z="0.0" unit="cm"/>
<rotation name="Rot012" x="0.0" y="120.0" z="240.0" unit="deg"/>
<position name="Pos012" x="-50.0" y="0.0" z="50.0" unit="cm"/>
<rotation name="Rot020" x="0.0" y="240.0" z="0.0" unit="deg"/>
<position name="Pos020" x="-50.0" y="50.0" z="-50.0" unit="cm"/>
<rotation name="Rot021" x="0.0" y="240.0" z="120.0" unit="deg"/>
<position name="Pos021" x="-50.0" y="50.0" z="0.0" unit="cm"/>
<rotation name="Rot022" x="0.0" y="240.0" z="240.0" unit="deg"/>
<position name="Pos022" x="-50.0" y="50.0" z="50.0" unit="cm"/>
<rotation name="Rot100" x="120.0" y="0.0" z="0.0" unit="deg"/>
<position name="Pos100" x="0.0" y="-50.0" z="-50.0" unit="cm"/>
<rotation name="Rot101" x="120.0" y="0.0" z="120.0" unit="deg"/>
<position name="Pos101" x="0.0" y="-50.0" z="0.0" unit="cm"/>
<rotation name="Rot102" x="120.0" y="0.0" z="240.0" unit="deg"/>
<position name="Pos102" x="0.0" y="-50.0" z="50.0" unit="cm"/>
<rotation name="Rot110" x="120.0" y="120.0" z="0.0" unit="deg"/>
<position name="Pos110" x="0.0" y="0.0" z="-50.0" unit="cm"/>
<rotation name="Rot111" x="120.0" y="120.0" z="120.0" unit="deg"/>
<position name="Pos111" x="0.0" y="0.0" z="0.0" unit="cm"/>
<rotation name="Rot112" x="120.0" y="120.0" z="240.0" unit="deg"/>
<position name="Pos112" x="0.0" y="0.0" z="50.0" unit="cm"/>
<rotation name="Rot120" x="120.0" y="240.0" z="0.0" unit="deg"/>
<position name="Pos120" x="0.0" y="50.0" z="-50.0" unit="cm"/>
<rotation name="Rot121" x="120.0" y="240.0" z="120.0" unit="deg"/>
<position name="Pos121" x="0.0" y="50.0" z="0.0" unit="cm"/>
<rotation name="Rot122" x="120.0" y="240.0" z="240.0" unit="deg"/>
<position name="Pos122" x="0.0" y="50.0" z="50.0" unit="cm"/>
<rotation name="Rot200" x="240.0" y="0.0" z="0.0" unit="deg"/>
<position name="Pos200" x="50.0" y="-50.0" z="-50.0" unit="cm"/>
<rotation name="Rot201" x="240.0" y="0.0" z="120.0" unit="deg"/>
<position name="Pos201" x="50.0" y="-50.0" z="0.0" unit="cm"/>
<rotation name="Rot202" x="240.0" y="0.0" z="240.0" unit="deg"/>
<position name="Pos202" x="50.0" y="-50.0" z="50.0" unit="cm"/>
<rotation name="Rot210" x="240.0" y="120.0" z="0.0" unit="deg"/>
<position name="Pos210" x="50.0" y="0.0" z="-50.0" unit="cm"/>
<rotation name="Rot211" x="240.0" y="120.0" z="120.0" unit="deg"/>
<position name="Pos211" x="50.0" y="0.0" z="0.0" unit="cm"/>
<rotation name="Rot212" x="240.0" y="120.0" z="240.0" unit="deg"/>
<position name="Pos212" x="50.0" y="0.0" z="50.0" unit="cm"/>
<rotation name="Rot220" x="240.0" y="240.0" z="0.0" unit="deg"/>
<position name="Pos220" x="50.0" y="50.0" z="-50.0" unit="cm"/>
<rotation name="Rot221" x="240.0" y="240.0" z="120.0" unit="deg"/>
<position name="Pos221" x="50.0" y="50.0" z="0.0" unit="cm"/>
<rotation name="Rot222" x="240.0" y="240.0" z="240.0" unit="deg"/>
<position name="Pos222" x="50.0" y="50.0" z="50.0" unit="cm"/>
</define>
<materials/>
<solids>
<tube aunit="degree" name="segment" rmax="20.0" z="5.0" rmin="17.0" startphi="0.0" deltaphi="60.0"/>
<box name="cave" x="200.0" y="200.0" z="200.0"/>
<box name="box" x="30.0" y="30.0" z="30.0"/>
</solids>
<structure>
<volume name="segment_vol">
<materialref ref="G4_WATER"/>
<solidref ref="segment"/>
</volume>
<volume name="composite">
<physvol name="segment_0">
<volumeref ref="segment_vol"/>
<positionref ref="center"/>
<rotationref ref="Rot0"/>
</physvol>
<physvol name="segment_1">
<volumeref ref="segment_vol"/>
<positionref ref="center"/>
<rotationref ref="Rot1"/>
</physvol>
<physvol name="segment_2">
<volumeref ref="segment_vol"/>
<positionref ref="center"/>
<rotationref ref="Rot2"/>
</physvol>
<physvol name="segment_3">
<volumeref ref="segment_vol"/>
<positionref ref="center"/>
<rotationref ref="Rot3"/>
</physvol>
<physvol name="segment_4">
<volumeref ref="segment_vol"/>
<positionref ref="center"/>
<rotationref ref="Rot4"/>
</physvol>
<physvol name="segment_5">
<volumeref ref="segment_vol"/>
<positionref ref="center"/>
<rotationref ref="Rot5"/>
</physvol>
<materialref ref="G4_AIR"/>
<solidref ref="box"/>
</volume>
<volume name="world">
<physvol name="composite_000">
<volumeref ref="composite"/>
<positionref ref="Pos000"/>
<rotationref ref="Rot000"/>
</physvol>
<physvol name="composite_001">
<volumeref ref="composite"/>
<positionref ref="Pos001"/>
<rotationref ref="Rot001"/>
</physvol>
<physvol name="composite_002">
<volumeref ref="composite"/>
<positionref ref="Pos002"/>
<rotationref ref="Rot002"/>
</physvol>
<physvol name="composite_003">
<volumeref ref="composite"/>
<positionref ref="Pos010"/>
<rotationref ref="Rot010"/>
</physvol>
<physvol name="composite_004">
<volumeref ref="composite"/>
<positionref ref="Pos011"/>
<rotationref ref="Rot011"/>
</physvol>
<physvol name="composite_005">
<volumeref ref="composite"/>
<positionref ref="Pos012"/>
<rotationref ref="Rot012"/>
</physvol>
<physvol name="composite_006">
<volumeref ref="composite"/>
<positionref ref="Pos020"/>
<rotationref ref="Rot020"/>
</physvol>
<physvol>
<volumeref ref="composite"/>
<positionref ref="Pos021"/>
<rotationref ref="Rot021"/>
</physvol>
<physvol>
<volumeref ref="composite"/>
<positionref ref="Pos022"/>
<rotationref ref="Rot022"/>
</physvol>
<physvol>
<volumeref ref="composite"/>
<positionref ref="Pos100"/>
<rotationref ref="Rot100"/>
</physvol>
<physvol>
<volumeref ref="composite"/>
<positionref ref="Pos101"/>
<rotationref ref="Rot101"/>
</physvol>
<physvol>
<volumeref ref="composite"/>
<positionref ref="Pos102"/>
<rotationref ref="Rot102"/>
</physvol>
<physvol>
<volumeref ref="composite"/>
<positionref ref="Pos110"/>
<rotationref ref="Rot110"/>
</physvol>
<physvol>
<volumeref ref="composite"/>
<positionref ref="Pos111"/>
<rotationref ref="Rot111"/>
</physvol>
<physvol>
<volumeref ref="composite"/>
<positionref ref="Pos112"/>
<rotationref ref="Rot112"/>
</physvol>
<physvol>
<volumeref ref="composite"/>
<positionref ref="Pos120"/>
<rotationref ref="Rot120"/>
</physvol>
<physvol>
<volumeref ref="composite"/>
<positionref ref="Pos121"/>
<rotationref ref="Rot121"/>
</physvol>
<physvol>
<volumeref ref="composite"/>
<positionref ref="Pos122"/>
<rotationref ref="Rot122"/>
</physvol>
<physvol>
<volumeref ref="composite"/>
<positionref ref="Pos200"/>
<rotationref ref="Rot200"/>
</physvol>
<physvol>
<volumeref ref="composite"/>
<positionref ref="Pos201"/>
<rotationref ref="Rot201"/>
</physvol>
<physvol>
<volumeref ref="composite"/>
<positionref ref="Pos202"/>
<rotationref ref="Rot202"/>
</physvol>
<physvol>
<volumeref ref="composite"/>
<positionref ref="Pos210"/>
<rotationref ref="Rot210"/>
</physvol>
<physvol>
<volumeref ref="composite"/>
<positionref ref="Pos211"/>
<rotationref ref="Rot211"/>
</physvol>
<physvol>
<volumeref ref="composite"/>
<positionref ref="Pos212"/>
<rotationref ref="Rot212"/>
</physvol>
<physvol>
<volumeref ref="composite"/>
<positionref ref="Pos220"/>
<rotationref ref="Rot220"/>
</physvol>
<physvol>
<volumeref ref="composite"/>
<positionref ref="Pos221"/>
<rotationref ref="Rot221"/>
</physvol>
<physvol>
<volumeref ref="composite"/>
<positionref ref="Pos222"/>
<rotationref ref="Rot222"/>
</physvol>
<materialref ref="G4_AIR"/>
<solidref ref="cave"/>
</volume>
</structure>
<setup name="Default" version="1.0">
<world ref="world"/>
</setup>
</gdml>

View File

@ -1,17 +1,12 @@
import org.openjfx.gradle.JavaFXOptions import scientifik.serialization
import scientifik.useSerialization
plugins { plugins {
id("scientifik.mpp") id("scientifik.mpp")
id("org.openjfx.javafxplugin")
} }
useSerialization() serialization()
kotlin { kotlin {
jvm {
withJava()
}
sourceSets { sourceSets {
commonMain { commonMain {
dependencies { dependencies {
@ -32,14 +27,9 @@ kotlin {
jsMain { jsMain {
dependencies { dependencies {
// api(project(":wrappers")) // api(project(":wrappers"))
implementation(npm("three", "0.106.2")) implementation(npm("three", "0.114.0"))
implementation(npm("@hi-level/three-csg", "1.0.6")) implementation(npm("three-csg-ts", "1.0.1"))
} }
} }
} }
} }
configure<JavaFXOptions> {
modules("javafx.controls")
}

View File

@ -2,15 +2,11 @@
package hep.dataforge.vis.spatial package hep.dataforge.vis.spatial
import hep.dataforge.context.Context import hep.dataforge.context.Context
import hep.dataforge.io.serialization.ConfigSerializer
import hep.dataforge.meta.Config import hep.dataforge.meta.Config
import hep.dataforge.meta.Meta import hep.dataforge.meta.Meta
import hep.dataforge.meta.float import hep.dataforge.meta.float
import hep.dataforge.meta.get import hep.dataforge.meta.get
import hep.dataforge.vis.common.AbstractVisualObject import hep.dataforge.vis.*
import hep.dataforge.vis.common.VisualFactory
import hep.dataforge.vis.common.VisualObject
import hep.dataforge.vis.common.set
import hep.dataforge.vis.spatial.Box.Companion.TYPE_NAME import hep.dataforge.vis.spatial.Box.Companion.TYPE_NAME
import kotlinx.serialization.SerialName import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
@ -29,7 +25,6 @@ class Box(
override var rotation: Point3D? = null override var rotation: Point3D? = null
override var scale: Point3D? = null override var scale: Point3D? = null
@Serializable(ConfigSerializer::class)
override var properties: Config? = null override var properties: Config? = null
//TODO add helper for color configuration //TODO add helper for color configuration
@ -69,7 +64,7 @@ class Box(
} }
} }
inline fun VisualGroup3D.box( inline fun MutableVisualGroup.box(
xSize: Number, xSize: Number,
ySize: Number, ySize: Number,
zSize: Number, zSize: Number,

View File

@ -2,11 +2,10 @@
package hep.dataforge.vis.spatial package hep.dataforge.vis.spatial
import hep.dataforge.io.serialization.ConfigSerializer
import hep.dataforge.meta.Config import hep.dataforge.meta.Config
import hep.dataforge.meta.update import hep.dataforge.meta.update
import hep.dataforge.vis.common.AbstractVisualObject import hep.dataforge.names.NameToken
import hep.dataforge.vis.common.set import hep.dataforge.vis.*
import kotlinx.serialization.SerialName import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
import kotlinx.serialization.UseSerializers import kotlinx.serialization.UseSerializers
@ -23,7 +22,7 @@ class Composite(
val compositeType: CompositeType, val compositeType: CompositeType,
val first: VisualObject3D, val first: VisualObject3D,
val second: VisualObject3D val second: VisualObject3D
) : AbstractVisualObject(), VisualObject3D { ) : AbstractVisualObject(), VisualObject3D, VisualGroup {
init { init {
first.parent = this first.parent = this
@ -34,11 +33,16 @@ class Composite(
override var rotation: Point3D? = null override var rotation: Point3D? = null
override var scale: Point3D? = null override var scale: Point3D? = null
@Serializable(ConfigSerializer::class)
override var properties: Config? = null override var properties: Config? = null
override val children: Map<NameToken, VisualObject>
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, type: CompositeType,
name: String = "", name: String = "",
builder: VisualGroup3D.() -> Unit builder: VisualGroup3D.() -> Unit
@ -50,24 +54,24 @@ inline fun VisualGroup3D.composite(
it.config.update(group.config) it.config.update(group.config)
//it.material = group.material //it.material = group.material
if(group.position!=null) { if (group.position != null) {
it.position = group.position it.position = group.position
} }
if(group.rotation!=null) { if (group.rotation != null) {
it.rotation = group.rotation it.rotation = group.rotation
} }
if(group.scale!=null) { if (group.scale != null) {
it.scale = group.scale it.scale = group.scale
} }
set(name, it) 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) 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) 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) composite(CompositeType.INTERSECT, name, builder = builder)

View File

@ -2,10 +2,10 @@
package hep.dataforge.vis.spatial package hep.dataforge.vis.spatial
import hep.dataforge.io.serialization.ConfigSerializer
import hep.dataforge.meta.Config import hep.dataforge.meta.Config
import hep.dataforge.vis.common.AbstractVisualObject import hep.dataforge.vis.AbstractVisualObject
import hep.dataforge.vis.common.set import hep.dataforge.vis.MutableVisualGroup
import hep.dataforge.vis.set
import kotlinx.serialization.SerialName import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
import kotlinx.serialization.UseSerializers import kotlinx.serialization.UseSerializers
@ -25,7 +25,6 @@ class ConeSegment(
var angle: Float = PI2 var angle: Float = PI2
) : AbstractVisualObject(), VisualObject3D, Shape { ) : AbstractVisualObject(), VisualObject3D, Shape {
@Serializable(ConfigSerializer::class)
override var properties: Config? = null override var properties: Config? = null
override var position: Point3D? = null override var position: Point3D? = null
@ -76,7 +75,7 @@ class ConeSegment(
} }
inline fun VisualGroup3D.cylinder( inline fun MutableVisualGroup.cylinder(
r: Number, r: Number,
height: Number, height: Number,
name: String = "", name: String = "",
@ -88,7 +87,7 @@ inline fun VisualGroup3D.cylinder(
).apply(block).also { set(name, it) } ).apply(block).also { set(name, it) }
inline fun VisualGroup3D.cone( inline fun MutableVisualGroup.cone(
bottomRadius: Number, bottomRadius: Number,
height: Number, height: Number,
upperRadius: Number = 0.0, upperRadius: Number = 0.0,

View File

@ -2,10 +2,10 @@
package hep.dataforge.vis.spatial package hep.dataforge.vis.spatial
import hep.dataforge.io.serialization.ConfigSerializer
import hep.dataforge.meta.Config import hep.dataforge.meta.Config
import hep.dataforge.vis.common.AbstractVisualObject import hep.dataforge.vis.AbstractVisualObject
import hep.dataforge.vis.common.set import hep.dataforge.vis.MutableVisualGroup
import hep.dataforge.vis.set
import kotlinx.serialization.SerialName import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
import kotlinx.serialization.UseSerializers import kotlinx.serialization.UseSerializers
@ -14,7 +14,6 @@ import kotlinx.serialization.UseSerializers
@SerialName("3d.convex") @SerialName("3d.convex")
class Convex(val points: List<Point3D>) : AbstractVisualObject(), VisualObject3D { class Convex(val points: List<Point3D>) : AbstractVisualObject(), VisualObject3D {
@Serializable(ConfigSerializer::class)
override var properties: Config? = null override var properties: Config? = null
override var position: Point3D? = null override var position: Point3D? = null
@ -26,7 +25,7 @@ class Convex(val points: List<Point3D>) : 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) } ConvexBuilder().apply(action).build().also { set(name, it) }
class ConvexBuilder { class ConvexBuilder {

View File

@ -1,10 +1,10 @@
@file:UseSerializers(Point2DSerializer::class, Point3DSerializer::class) @file:UseSerializers(Point2DSerializer::class, Point3DSerializer::class)
package hep.dataforge.vis.spatial package hep.dataforge.vis.spatial
import hep.dataforge.io.serialization.ConfigSerializer
import hep.dataforge.meta.Config import hep.dataforge.meta.Config
import hep.dataforge.vis.common.AbstractVisualObject import hep.dataforge.vis.AbstractVisualObject
import hep.dataforge.vis.common.set import hep.dataforge.vis.MutableVisualGroup
import hep.dataforge.vis.set
import kotlinx.serialization.SerialName import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
import kotlinx.serialization.UseSerializers import kotlinx.serialization.UseSerializers
@ -45,7 +45,6 @@ class Extruded(
var layers: MutableList<Layer> = ArrayList() var layers: MutableList<Layer> = ArrayList()
) : AbstractVisualObject(), VisualObject3D, Shape { ) : AbstractVisualObject(), VisualObject3D, Shape {
@Serializable(ConfigSerializer::class)
override var properties: Config? = null override var properties: Config? = null
override var position: Point3D? = 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) } Extruded().apply(action).also { set(name, it) }

View File

@ -1,6 +1,5 @@
package hep.dataforge.vis.spatial package hep.dataforge.vis.spatial
import hep.dataforge.meta.EmptyMeta
import hep.dataforge.meta.Meta import hep.dataforge.meta.Meta
/** /**
@ -14,7 +13,7 @@ interface GeometryBuilder<T : Any> {
* @param normal optional external normal to the face * @param normal optional external normal to the face
* @param meta optional additional platform-specific parameters like color or texture index * @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 fun build(): T
} }
@ -25,7 +24,7 @@ fun GeometryBuilder<*>.face4(
vertex3: Point3D, vertex3: Point3D,
vertex4: Point3D, vertex4: Point3D,
normal: Point3D? = null, normal: Point3D? = null,
meta: Meta = EmptyMeta meta: Meta = Meta.EMPTY
) { ) {
face(vertex1, vertex2, vertex3, normal, meta) face(vertex1, vertex2, vertex3, normal, meta)
face(vertex1, vertex3, vertex4, normal, meta) face(vertex1, vertex3, vertex4, normal, meta)

View File

@ -2,19 +2,17 @@
package hep.dataforge.vis.spatial package hep.dataforge.vis.spatial
import hep.dataforge.io.serialization.ConfigSerializer
import hep.dataforge.meta.Config import hep.dataforge.meta.Config
import hep.dataforge.vis.common.AbstractVisualObject import hep.dataforge.vis.AbstractVisualObject
import hep.dataforge.vis.common.set import hep.dataforge.vis.MutableVisualGroup
import hep.dataforge.vis.set
import kotlinx.serialization.SerialName import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
import kotlinx.serialization.UseSerializers import kotlinx.serialization.UseSerializers
@Serializable @Serializable
@SerialName("3d.label") @SerialName("3d.label")
class Label3D(var text: String, var fontSize: Double, var fontFamily: String) : AbstractVisualObject(), class Label3D(var text: String, var fontSize: Double, var fontFamily: String) : AbstractVisualObject(), VisualObject3D {
VisualObject3D {
@Serializable(ConfigSerializer::class)
override var properties: Config? = null override var properties: Config? = null
override var position: Point3D? = 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, text: String,
fontSize: Number = 20, fontSize: Number = 20,
fontFamily: String = "Arial", fontFamily: String = "Arial",

View File

@ -1,16 +1,17 @@
package hep.dataforge.vis.spatial package hep.dataforge.vis.spatial
import hep.dataforge.descriptors.NodeDescriptor
import hep.dataforge.meta.* import hep.dataforge.meta.*
import hep.dataforge.meta.descriptors.NodeDescriptor
import hep.dataforge.names.asName import hep.dataforge.names.asName
import hep.dataforge.names.plus import hep.dataforge.names.plus
import hep.dataforge.values.ValueType 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_COLOR_KEY
import hep.dataforge.vis.spatial.Material3D.Companion.MATERIAL_KEY import hep.dataforge.vis.spatial.Material3D.Companion.MATERIAL_KEY
import hep.dataforge.vis.spatial.Material3D.Companion.MATERIAL_OPACITY_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 * Primary web-color for the material
@ -32,8 +33,7 @@ class Material3D(override val config: Config) : Specific {
*/ */
var wireframe by boolean(false, WIREFRAME_KEY) var wireframe by boolean(false, WIREFRAME_KEY)
companion object : Specification<Material3D> { companion object : SchemeSpec<Material3D>(::Material3D) {
override fun wrap(config: Config): Material3D = Material3D(config)
val MATERIAL_KEY = "material".asName() val MATERIAL_KEY = "material".asName()
internal val COLOR_KEY = "color".asName() internal val COLOR_KEY = "color".asName()
@ -44,23 +44,26 @@ class Material3D(override val config: Config) : Specific {
internal val WIREFRAME_KEY = "wireframe".asName() internal val WIREFRAME_KEY = "wireframe".asName()
val MATERIAL_WIREFRAME_KEY = MATERIAL_KEY + WIREFRAME_KEY val MATERIAL_WIREFRAME_KEY = MATERIAL_KEY + WIREFRAME_KEY
val descriptor = NodeDescriptor { val descriptor by lazy {
value(VisualObject3D.VISIBLE_KEY) { //must be lazy to avoid initialization bug
type(ValueType.BOOLEAN) NodeDescriptor {
default(true) defineValue(VisualObject3D.VISIBLE_KEY) {
}
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) {
type(ValueType.BOOLEAN) 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 * Set color as web-color
*/ */
fun VisualObject3D.color(webColor: String) { fun VisualObject3D.color(webColor: String) {
setProperty(MATERIAL_COLOR_KEY, webColor) setProperty(MATERIAL_COLOR_KEY, webColor.asValue())
} }
/** /**
* Set color as integer * Set color as integer
*/ */
fun VisualObject3D.color(rgb: Int) { 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( 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? var VisualObject3D.color: String?
get() = getProperty(MATERIAL_COLOR_KEY)?.let { Colors.fromMeta(it) } get() = getProperty(MATERIAL_COLOR_KEY)?.let { Colors.fromMeta(it) }
set(value) { set(value) {
setProperty(MATERIAL_COLOR_KEY, value) setProperty(MATERIAL_COLOR_KEY, value?.asValue())
} }
val VisualObject3D.material: Material3D? val VisualObject3D.material: Material3D?
@ -110,5 +113,5 @@ fun VisualObject3D.material(builder: Material3D.() -> Unit) {
var VisualObject3D.opacity: Double? var VisualObject3D.opacity: Double?
get() = getProperty(MATERIAL_OPACITY_KEY).double get() = getProperty(MATERIAL_OPACITY_KEY).double
set(value) { set(value) {
setProperty(MATERIAL_OPACITY_KEY, value) setProperty(MATERIAL_OPACITY_KEY, value?.asValue())
} }

View File

@ -2,13 +2,13 @@
package hep.dataforge.vis.spatial package hep.dataforge.vis.spatial
import hep.dataforge.io.serialization.ConfigSerializer
import hep.dataforge.meta.Config import hep.dataforge.meta.Config
import hep.dataforge.meta.number import hep.dataforge.meta.number
import hep.dataforge.names.asName import hep.dataforge.names.asName
import hep.dataforge.names.plus import hep.dataforge.names.plus
import hep.dataforge.vis.common.AbstractVisualObject import hep.dataforge.vis.AbstractVisualObject
import hep.dataforge.vis.common.set import hep.dataforge.vis.MutableVisualGroup
import hep.dataforge.vis.set
import kotlinx.serialization.SerialName import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
import kotlinx.serialization.UseSerializers import kotlinx.serialization.UseSerializers
@ -16,7 +16,6 @@ import kotlinx.serialization.UseSerializers
@Serializable @Serializable
@SerialName("3d.line") @SerialName("3d.line")
class PolyLine(var points: List<Point3D>) : AbstractVisualObject(), VisualObject3D { class PolyLine(var points: List<Point3D>) : AbstractVisualObject(), VisualObject3D {
@Serializable(ConfigSerializer::class)
override var properties: Config? = null override var properties: Config? = null
override var position: Point3D? = null override var position: Point3D? = null
@ -32,5 +31,5 @@ class PolyLine(var points: List<Point3D>) : 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) } PolyLine(points.toList()).apply(action).also { set(name, it) }

View File

@ -1,18 +1,13 @@
@file:UseSerializers(Point3DSerializer::class, NameSerializer::class, ConfigSerializer::class) @file:UseSerializers(Point3DSerializer::class)
package hep.dataforge.vis.spatial 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.Config
import hep.dataforge.meta.Laminate import hep.dataforge.meta.Laminate
import hep.dataforge.meta.MetaItem import hep.dataforge.meta.MetaItem
import hep.dataforge.meta.get import hep.dataforge.meta.get
import hep.dataforge.names.Name import hep.dataforge.names.*
import hep.dataforge.names.NameToken import hep.dataforge.vis.*
import hep.dataforge.names.asName
import hep.dataforge.names.plus
import hep.dataforge.vis.common.*
import kotlinx.serialization.SerialName import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
import kotlinx.serialization.Transient import kotlinx.serialization.Transient
@ -26,7 +21,9 @@ import kotlin.collections.set
*/ */
@Serializable @Serializable
@SerialName("3d.proxy") @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) { constructor(parent: VisualGroup3D, templateName: Name) : this(templateName) {
this.parent = parent this.parent = parent
@ -36,7 +33,6 @@ class Proxy private constructor(val templateName: Name) : AbstractVisualObject()
override var rotation: Point3D? = null override var rotation: Point3D? = null
override var scale: Point3D? = null override var scale: Point3D? = null
@Serializable(ConfigSerializer::class)
override var properties: Config? = null override var properties: Config? = null
/** /**
@ -44,10 +40,12 @@ class Proxy private constructor(val templateName: Name) : AbstractVisualObject()
*/ */
val prototype: VisualObject3D val prototype: VisualObject3D
get() = (parent as? VisualGroup3D)?.getPrototype(templateName) 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 override val styleSheet: StyleSheet
get() = (parent as? VisualGroup)?.styleSheet ?: StyleSheet(this) get() = parent?.styleSheet ?: StyleSheet(
this
)
override fun getProperty(name: Name, inherit: Boolean): MetaItem<*>? { override fun getProperty(name: Name, inherit: Boolean): MetaItem<*>? {
return if (inherit) { 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) }) //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) val prototype: VisualObject get() = prototypeFor(name)
@ -155,20 +154,18 @@ val VisualObject.prototype: VisualObject
/** /**
* Create ref for existing prototype * Create ref for existing prototype
*/ */
inline fun VisualGroup3D.ref( fun VisualGroup3D.ref(
templateName: Name, templateName: Name,
name: String = "", name: String = ""
block: Proxy.() -> Unit = {} ): Proxy = Proxy(this, templateName).also { set(name, it) }
) = Proxy(this, templateName).apply(block).also { set(name, it) }
/** /**
* Add new proxy wrapping given object and automatically adding it to the prototypes * Add new proxy wrapping given object and automatically adding it to the prototypes
*/ */
fun VisualGroup3D.proxy( fun VisualGroup3D.proxy(
templateName: Name, name: String,
obj: VisualObject3D, obj: VisualObject3D,
name: String = "", templateName: Name = name.toName()
block: Proxy.() -> Unit = {}
): Proxy { ): Proxy {
val existing = getPrototype(templateName) val existing = getPrototype(templateName)
if (existing == null) { if (existing == null) {
@ -178,5 +175,14 @@ fun VisualGroup3D.proxy(
} else if (existing != obj) { } else if (existing != obj) {
error("Can't add different prototype on top of existing one") 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)
} }

View File

@ -2,10 +2,10 @@
package hep.dataforge.vis.spatial package hep.dataforge.vis.spatial
import hep.dataforge.io.serialization.ConfigSerializer
import hep.dataforge.meta.Config import hep.dataforge.meta.Config
import hep.dataforge.vis.common.AbstractVisualObject import hep.dataforge.vis.AbstractVisualObject
import hep.dataforge.vis.common.set import hep.dataforge.vis.MutableVisualGroup
import hep.dataforge.vis.set
import kotlinx.serialization.SerialName import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
import kotlinx.serialization.UseSerializers import kotlinx.serialization.UseSerializers
@ -23,7 +23,6 @@ class Sphere(
var theta: Float = PI.toFloat() var theta: Float = PI.toFloat()
) : AbstractVisualObject(), VisualObject3D, Shape { ) : AbstractVisualObject(), VisualObject3D, Shape {
@Serializable(ConfigSerializer::class)
override var properties: Config? = null override var properties: Config? = null
override var position: Point3D? = null override var position: Point3D? = null
@ -61,7 +60,7 @@ class Sphere(
} }
} }
inline fun VisualGroup3D.sphere( inline fun MutableVisualGroup.sphere(
radius: Number, radius: Number,
phi: Number = 2 * PI, phi: Number = 2 * PI,
theta: Number = PI, theta: Number = PI,

View File

@ -1,10 +1,10 @@
@file:UseSerializers(Point3DSerializer::class) @file:UseSerializers(Point3DSerializer::class)
package hep.dataforge.vis.spatial package hep.dataforge.vis.spatial
import hep.dataforge.io.serialization.ConfigSerializer
import hep.dataforge.meta.Config import hep.dataforge.meta.Config
import hep.dataforge.vis.common.AbstractVisualObject import hep.dataforge.vis.AbstractVisualObject
import hep.dataforge.vis.common.set import hep.dataforge.vis.MutableVisualGroup
import hep.dataforge.vis.set
import kotlinx.serialization.SerialName import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
import kotlinx.serialization.UseSerializers import kotlinx.serialization.UseSerializers
@ -29,7 +29,6 @@ class Tube(
override var rotation: Point3D? = null override var rotation: Point3D? = null
override var scale: Point3D? = null override var scale: Point3D? = null
@Serializable(ConfigSerializer::class)
override var properties: Config? = null override var properties: Config? = null
init { init {
@ -129,7 +128,7 @@ class Tube(
} }
inline fun VisualGroup3D.tube( inline fun MutableVisualGroup.tube(
r: Number, r: Number,
height: Number, height: Number,
innerRadius: Number = 0f, innerRadius: Number = 0f,

View File

@ -4,14 +4,12 @@ import hep.dataforge.context.AbstractPlugin
import hep.dataforge.context.Context import hep.dataforge.context.Context
import hep.dataforge.context.PluginFactory import hep.dataforge.context.PluginFactory
import hep.dataforge.context.PluginTag 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.meta.*
import hep.dataforge.names.Name import hep.dataforge.names.Name
import hep.dataforge.names.toName import hep.dataforge.names.toName
import hep.dataforge.vis.common.Visual import hep.dataforge.vis.SimpleVisualGroup
import hep.dataforge.vis.common.VisualObject import hep.dataforge.vis.Visual
import hep.dataforge.vis.VisualObject
import kotlinx.serialization.json.Json import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonConfiguration import kotlinx.serialization.json.JsonConfiguration
import kotlinx.serialization.modules.SerializersModule import kotlinx.serialization.modules.SerializersModule
@ -39,29 +37,28 @@ class Visual3D(meta: Meta) : AbstractPlugin(meta) {
val serialModule = SerializersModule { val serialModule = SerializersModule {
contextual(Point3DSerializer) contextual(Point3DSerializer)
contextual(Point2DSerializer) contextual(Point2DSerializer)
contextual(NameSerializer)
contextual(NameTokenSerializer)
contextual(MetaSerializer)
contextual(ConfigSerializer)
polymorphic(VisualObject::class, VisualObject3D::class) { polymorphic(VisualObject::class, VisualObject3D::class) {
VisualGroup3D::class with VisualGroup3D.serializer() subclass(SimpleVisualGroup.serializer())
Proxy::class with Proxy.serializer() subclass(VisualGroup3D.serializer())
Composite::class with Composite.serializer() subclass(Proxy.serializer())
Tube::class with Tube.serializer() subclass(Composite.serializer())
Box::class with Box.serializer() subclass(Tube.serializer())
Convex::class with Convex.serializer() subclass(Box.serializer())
Extruded::class with Extruded.serializer() subclass(Convex.serializer())
addSubclass(PolyLine.serializer()) subclass(Extruded.serializer())
addSubclass(Label3D.serializer()) subclass(PolyLine.serializer())
subclass(Label3D.serializer())
subclass(Sphere.serializer())
} }
} }
val json = Json( internal val json = Json(
JsonConfiguration( JsonConfiguration(
prettyPrint = true, prettyPrint = true,
useArrayPolymorphism = false, useArrayPolymorphism = false,
encodeDefaults = false encodeDefaults = false,
ignoreUnknownKeys = true
), ),
context = serialModule context = serialModule
) )

View File

@ -1,48 +1,49 @@
@file:UseSerializers( @file:UseSerializers(
Point3DSerializer::class, Point3DSerializer::class
ConfigSerializer::class,
NameTokenSerializer::class,
NameSerializer::class,
MetaSerializer::class
) )
package hep.dataforge.vis.spatial 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.meta.Config
import hep.dataforge.names.Name import hep.dataforge.names.Name
import hep.dataforge.names.NameToken import hep.dataforge.names.NameToken
import hep.dataforge.names.asName import hep.dataforge.names.asName
import hep.dataforge.names.isEmpty import hep.dataforge.vis.*
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 kotlinx.serialization.SerialName import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
import kotlinx.serialization.UseSerializers import kotlinx.serialization.UseSerializers
import kotlin.collections.set import kotlin.collections.set
interface PrototypeHolder {
val parent: VisualGroup?
val prototypes: MutableVisualGroup?
}
/** /**
* Represents 3-dimensional Visual Group * Represents 3-dimensional Visual Group
*/ */
@Serializable @Serializable
@SerialName("group.3d") @SerialName("group.3d")
class VisualGroup3D : AbstractVisualGroup(), VisualObject3D { class VisualGroup3D : AbstractVisualGroup(), VisualObject3D, PrototypeHolder {
override var styleSheet: StyleSheet? = null override var styleSheet: StyleSheet? = null
private set
/** /**
* A container for templates visible inside this group * A container for templates visible inside this group
*/ */
var prototypes: VisualGroup3D? = null @Serializable(PrototypesSerializer::class)
set(value) { override var prototypes: MutableVisualGroup? = null
value?.parent = this private set
field = value
} /**
* 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 //FIXME to be lifted to AbstractVisualGroup after https://github.com/Kotlin/kotlinx.serialization/issues/378 is fixed
override var properties: Config? = null override var properties: Config? = null
@ -55,38 +56,18 @@ class VisualGroup3D : AbstractVisualGroup(), VisualObject3D {
private val _children = HashMap<NameToken, VisualObject>() private val _children = HashMap<NameToken, VisualObject>()
override val children: Map<NameToken, VisualObject> get() = _children override val children: Map<NameToken, VisualObject> get() = _children
// init {
// //Do after deserialization
// attachChildren()
// }
override fun attachChildren() { override fun attachChildren() {
prototypes?.parent = this prototypes?.parent = this
prototypes?.attachChildren() prototypes?.attachChildren()
super.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) { override fun removeChild(token: NameToken) {
_children.remove(token)?.run { parent = null } _children.remove(token)?.apply { parent = null }
childrenChanged(token.asName(), null)
} }
override fun setChild(token: NameToken, child: VisualObject) { 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 _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 addStatic(child: VisualObject) = setChild(NameToken("@static(${child.hashCode()})"), child)
override fun createGroup(name: Name): VisualGroup3D { override fun createGroup(): VisualGroup3D = 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())
}
}
companion object { companion object {
// val PROTOTYPES_KEY = NameToken("@prototypes") // val PROTOTYPES_KEY = NameToken("@prototypes")
fun fromJson(json: String): VisualGroup3D = fun parseJson(json: String): VisualGroup3D =
Visual3D.json.parse(serializer(), json).also { it.attachChildren() } 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 * 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) 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 { fun MutableVisualGroup.group(name: String = "", action: VisualGroup3D.() -> Unit = {}): VisualGroup3D =
(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 =
VisualGroup3D().apply(action).also { VisualGroup3D().apply(action).also {
set(key, it) set(name, it)
} }
internal class Prototypes(
override var children: MutableMap<NameToken, VisualObject> = 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()
}
}
}

View File

@ -1,13 +1,15 @@
@file:UseSerializers(Point3DSerializer::class, NameSerializer::class, NameTokenSerializer::class) @file:UseSerializers(Point3DSerializer::class)
package hep.dataforge.vis.spatial package hep.dataforge.vis.spatial
import hep.dataforge.io.serialization.NameSerializer
import hep.dataforge.meta.* import hep.dataforge.meta.*
import hep.dataforge.meta.descriptors.NodeDescriptor
import hep.dataforge.names.asName import hep.dataforge.names.asName
import hep.dataforge.names.plus import hep.dataforge.names.plus
import hep.dataforge.output.Renderer 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.DETAIL_KEY
import hep.dataforge.vis.spatial.VisualObject3D.Companion.IGNORE_KEY import hep.dataforge.vis.spatial.VisualObject3D.Companion.IGNORE_KEY
import hep.dataforge.vis.spatial.VisualObject3D.Companion.LAYER_KEY import hep.dataforge.vis.spatial.VisualObject3D.Companion.LAYER_KEY
@ -25,7 +27,8 @@ interface VisualObject3D : VisualObject {
companion object { companion object {
val VISIBLE_KEY = "visible".asName() val VISIBLE_KEY = "visible".asName()
// val SELECTED_KEY = "selected".asName()
// val SELECTED_KEY = "selected".asName()
val DETAIL_KEY = "detail".asName() val DETAIL_KEY = "detail".asName()
val LAYER_KEY = "layer".asName() val LAYER_KEY = "layer".asName()
val IGNORE_KEY = "ignore".asName() val IGNORE_KEY = "ignore".asName()
@ -55,6 +58,22 @@ interface VisualObject3D : VisualObject {
val xScale = scale + x val xScale = scale + x
val yScale = scale + y val yScale = scale + y
val zScale = scale + z 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 var VisualObject3D.layer: Int
get() = getProperty(LAYER_KEY).int ?: 0 get() = getProperty(LAYER_KEY).int ?: 0
set(value) { set(value) {
setProperty(LAYER_KEY, value) setProperty(LAYER_KEY, value.asValue())
} }
fun Renderer<VisualObject3D>.render(meta: Meta = EmptyMeta, action: VisualGroup3D.() -> Unit) = fun Renderer<VisualObject3D>.render(meta: Meta = Meta.EMPTY, action: VisualGroup3D.() -> Unit) =
render(VisualGroup3D().apply(action), meta) render(VisualGroup3D().apply(action), meta)
// Common properties // Common properties
@ -86,7 +105,7 @@ enum class RotationOrder {
*/ */
var VisualObject3D.rotationOrder: RotationOrder var VisualObject3D.rotationOrder: RotationOrder
get() = getProperty(VisualObject3D.rotationOrder).enum<RotationOrder>() ?: RotationOrder.XYZ get() = getProperty(VisualObject3D.rotationOrder).enum<RotationOrder>() ?: 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? var VisualObject3D.detail: Int?
get() = getProperty(DETAIL_KEY, false).int get() = getProperty(DETAIL_KEY, false).int
set(value) = setProperty(DETAIL_KEY, value) set(value) = setProperty(DETAIL_KEY, value?.asValue())
var VisualObject.visible: Boolean? var VisualObject.visible: Boolean?
get() = getProperty(VISIBLE_KEY).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. * If this property is true, the object will be ignored on render.
* Property is not inherited. * Property is not inherited.
*/ */
var VisualObject.ignore: Boolean? var VisualObject.ignore: Boolean?
get() = getProperty(IGNORE_KEY,false).boolean get() = getProperty(IGNORE_KEY, false).boolean
set(value) = setProperty(IGNORE_KEY, value) set(value) = setProperty(IGNORE_KEY, value?.asValue())
//var VisualObject.selected: Boolean? //var VisualObject.selected: Boolean?
// get() = getProperty(SELECTED_KEY).boolean // get() = getProperty(SELECTED_KEY).boolean

View File

@ -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()

View File

@ -1,9 +1,16 @@
package hep.dataforge.vis.spatial package hep.dataforge.vis.spatial
import hep.dataforge.meta.Meta import hep.dataforge.meta.Meta
import hep.dataforge.meta.buildMeta
import hep.dataforge.meta.get import hep.dataforge.meta.get
import hep.dataforge.meta.number 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) { expect class Point2D(x: Number, y: Number) {
var x: Double var x: Double
@ -13,7 +20,7 @@ expect class Point2D(x: Number, y: Number) {
operator fun Point2D.component1() = x operator fun Point2D.component1() = x
operator fun Point2D.component2() = y operator fun Point2D.component2() = y
fun Point2D.toMeta() = buildMeta { fun Point2D.toMeta() = Meta {
VisualObject3D.x put x VisualObject3D.x put x
VisualObject3D.y put y 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 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.x put x
VisualObject3D.y put y VisualObject3D.y put y
VisualObject3D.z put z VisualObject3D.z put z

View File

@ -1,17 +1,19 @@
package hep.dataforge.vis.spatial 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.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.*
import kotlinx.serialization.internal.DoubleSerializer import kotlinx.serialization.builtins.MapSerializer
import kotlinx.serialization.internal.StringDescriptor import kotlinx.serialization.builtins.nullable
import kotlinx.serialization.internal.nullable import kotlinx.serialization.builtins.serializer
inline fun <R> Decoder.decodeStructure( inline fun <R> Decoder.decodeStructure(
desc: SerialDescriptor, desc: SerialDescriptor,
vararg typeParams: KSerializer<*> = emptyArray(), vararg typeParams: KSerializer<*> = emptyArray(),
crossinline block: CompositeDecoder.() -> R crossinline block: CompositeDecoder.() -> R
): R { ): R {
val decoder = beginStructure(desc, *typeParams) val decoder = beginStructure(desc, *typeParams)
val res = decoder.block() val res = decoder.block()
@ -31,7 +33,7 @@ inline fun Encoder.encodeStructure(
@Serializer(Point3D::class) @Serializer(Point3D::class)
object Point3DSerializer : KSerializer<Point3D> { object Point3DSerializer : KSerializer<Point3D> {
override val descriptor: SerialDescriptor = descriptor("hep.dataforge.vis.spatial.Point3D") { override val descriptor: SerialDescriptor = SerialDescriptor("hep.dataforge.vis.spatial.Point3D") {
double("x", true) double("x", true)
double("y", true) double("y", true)
double("z", true) double("z", true)
@ -45,28 +47,28 @@ object Point3DSerializer : KSerializer<Point3D> {
loop@ while (true) { loop@ while (true) {
when (val i = decodeElementIndex(descriptor)) { when (val i = decodeElementIndex(descriptor)) {
CompositeDecoder.READ_DONE -> break@loop CompositeDecoder.READ_DONE -> break@loop
0 -> x = decodeNullableSerializableElement(descriptor, 0, DoubleSerializer.nullable) ?: 0.0 0 -> x = decodeNullableSerializableElement(descriptor, 0, Double.serializer().nullable) ?: 0.0
1 -> y = decodeNullableSerializableElement(descriptor, 1, DoubleSerializer.nullable) ?: 0.0 1 -> y = decodeNullableSerializableElement(descriptor, 1, Double.serializer().nullable) ?: 0.0
2 -> z = decodeNullableSerializableElement(descriptor, 2, DoubleSerializer.nullable) ?: 0.0 2 -> z = decodeNullableSerializableElement(descriptor, 2, Double.serializer().nullable) ?: 0.0
else -> throw SerializationException("Unknown index $i") 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) { encoder.encodeStructure(descriptor) {
if (obj.x != 0.0) encodeDoubleElement(descriptor, 0, obj.x) if (value.x != 0.0) encodeDoubleElement(descriptor, 0, value.x)
if (obj.y != 0.0) encodeDoubleElement(descriptor, 1, obj.y) if (value.y != 0.0) encodeDoubleElement(descriptor, 1, value.y)
if (obj.z != 0.0) encodeDoubleElement(descriptor, 2, obj.z) if (value.z != 0.0) encodeDoubleElement(descriptor, 2, value.z)
} }
} }
} }
@Serializer(Point2D::class) @Serializer(Point2D::class)
object Point2DSerializer : KSerializer<Point2D> { object Point2DSerializer : KSerializer<Point2D> {
override val descriptor: SerialDescriptor = descriptor("hep.dataforge.vis.spatial.Point2D") { override val descriptor: SerialDescriptor = SerialDescriptor("hep.dataforge.vis.spatial.Point2D") {
double("x", true) double("x", true)
double("y", true) double("y", true)
} }
@ -78,32 +80,48 @@ object Point2DSerializer : KSerializer<Point2D> {
loop@ while (true) { loop@ while (true) {
when (val i = decodeElementIndex(descriptor)) { when (val i = decodeElementIndex(descriptor)) {
CompositeDecoder.READ_DONE -> break@loop CompositeDecoder.READ_DONE -> break@loop
0 -> x = decodeNullableSerializableElement(descriptor, 0, DoubleSerializer.nullable) ?: 0.0 0 -> x = decodeNullableSerializableElement(descriptor, 0, Double.serializer().nullable) ?: 0.0
1 -> y = decodeNullableSerializableElement(descriptor, 1, DoubleSerializer.nullable) ?: 0.0 1 -> y = decodeNullableSerializableElement(descriptor, 1, Double.serializer().nullable) ?: 0.0
else -> throw SerializationException("Unknown index $i") 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) { encoder.encodeStructure(descriptor) {
if (obj.x != 0.0) encodeDoubleElement(descriptor, 0, obj.x) if (value.x != 0.0) encodeDoubleElement(descriptor, 0, value.x)
if (obj.y != 0.0) encodeDoubleElement(descriptor, 1, obj.y) if (value.y != 0.0) encodeDoubleElement(descriptor, 1, value.y)
} }
} }
} }
@Serializer(NameToken::class) @Serializer(MutableVisualGroup::class)
object NameTokenSerializer : KSerializer<NameToken> { internal object PrototypesSerializer : KSerializer<MutableVisualGroup> {
override val descriptor: SerialDescriptor = StringDescriptor.withName("NameToken")
override fun deserialize(decoder: Decoder): NameToken { private val mapSerializer: KSerializer<Map<NameToken, VisualObject>> =
return decoder.decodeString().toName().first()!! 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<NameToken, VisualObject> ?: LinkedHashMap(map))
} }
override fun serialize(encoder: Encoder, obj: NameToken) { override fun serialize(encoder: Encoder, value: MutableVisualGroup) {
encoder.encodeString(obj.toString()) 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()
} }
} }

View File

@ -2,16 +2,13 @@ package hep.dataforge.vis.spatial.specifications
import hep.dataforge.meta.* import hep.dataforge.meta.*
class AxesSpec(override val config: Config) : Specific { class Axes : Scheme() {
var visible by boolean(!config.isEmpty()) var visible by boolean(!config.isEmpty())
var size by double(AXIS_SIZE) var size by double(AXIS_SIZE)
var width by double(AXIS_WIDTH) var width by double(AXIS_WIDTH)
companion object : Specification<AxesSpec> { companion object : SchemeSpec<Axes>(::Axes) {
override fun wrap(config: Config): AxesSpec = AxesSpec(config)
const val AXIS_SIZE = 1000.0 const val AXIS_SIZE = 1000.0
const val AXIS_WIDTH = 3.0 const val AXIS_WIDTH = 3.0
} }
} }

View File

@ -1,10 +1,14 @@
package hep.dataforge.vis.spatial.specifications 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 import kotlin.math.PI
class CameraSpec(override val config: Config) : Specific { class Camera : Scheme() {
var fov by int(FIELD_OF_VIEW) var fov by int(FIELD_OF_VIEW)
//var aspect by double(1.0) //var aspect by double(1.0)
var nearClip by double(NEAR_CLIP) var nearClip by double(NEAR_CLIP)
var farClip by double(FAR_CLIP) var farClip by double(FAR_CLIP)
@ -14,11 +18,10 @@ class CameraSpec(override val config: Config) : Specific {
var latitude by double(INITIAL_LATITUDE) var latitude by double(INITIAL_LATITUDE)
val zenith: Double get() = PI / 2 - latitude val zenith: Double get() = PI / 2 - latitude
companion object : Specification<CameraSpec> { companion object : SchemeSpec<Camera>(::Camera) {
override fun wrap(config: Config): CameraSpec = CameraSpec(config)
const val INITIAL_DISTANCE = 300.0 const val INITIAL_DISTANCE = 300.0
const val INITIAL_AZIMUTH = 0.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 NEAR_CLIP = 0.1
const val FAR_CLIP = 10000.0 const val FAR_CLIP = 10000.0
const val FIELD_OF_VIEW = 75 const val FIELD_OF_VIEW = 75

View File

@ -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>(::Canvas)
}

View File

@ -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<CanvasSpec>{
override fun wrap(config: Config): CanvasSpec = CanvasSpec(config)
}
}

View File

@ -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>(::Controls)
}

View File

@ -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<ControlsSpec> {
override fun wrap(config: Config): ControlsSpec = ControlsSpec(config)
}
}

View File

@ -2,9 +2,9 @@ package hep.dataforge.vis.spatial.transform
import hep.dataforge.meta.update import hep.dataforge.meta.update
import hep.dataforge.names.asName import hep.dataforge.names.asName
import hep.dataforge.vis.common.MutableVisualGroup import hep.dataforge.vis.MutableVisualGroup
import hep.dataforge.vis.common.VisualGroup import hep.dataforge.vis.VisualGroup
import hep.dataforge.vis.common.VisualObject import hep.dataforge.vis.VisualObject
import hep.dataforge.vis.spatial.* import hep.dataforge.vis.spatial.*
internal fun mergeChild(parent: VisualGroup, child: VisualObject): VisualObject { internal fun mergeChild(parent: VisualGroup, child: VisualObject): VisualObject {

View File

@ -2,11 +2,10 @@ package hep.dataforge.vis.spatial.transform
import hep.dataforge.names.Name import hep.dataforge.names.Name
import hep.dataforge.names.asName import hep.dataforge.names.asName
import hep.dataforge.vis.common.MutableVisualGroup import hep.dataforge.vis.MutableVisualGroup
import hep.dataforge.vis.common.VisualGroup import hep.dataforge.vis.VisualGroup
import hep.dataforge.vis.spatial.Proxy import hep.dataforge.vis.spatial.Proxy
import hep.dataforge.vis.spatial.VisualGroup3D import hep.dataforge.vis.spatial.VisualGroup3D
import hep.dataforge.vis.spatial.prototypes
object UnRef : VisualTreeTransform<VisualGroup3D>() { object UnRef : VisualTreeTransform<VisualGroup3D>() {
private fun VisualGroup.countRefs(): Map<Name, Int> { private fun VisualGroup.countRefs(): Map<Name, Int> {

View File

@ -1,6 +1,6 @@
package hep.dataforge.vis.spatial.transform package hep.dataforge.vis.spatial.transform
import hep.dataforge.vis.common.VisualObject import hep.dataforge.vis.VisualObject
/** /**
* A root class for [VisualObject] tree optimization * A root class for [VisualObject] tree optimization

View File

@ -1,8 +1,9 @@
package hep.dataforge.vis.spatial package hep.dataforge.vis.spatial
import hep.dataforge.io.toMeta
import hep.dataforge.meta.MetaItem import hep.dataforge.meta.MetaItem
import hep.dataforge.meta.getIndexed import hep.dataforge.meta.getIndexed
import hep.dataforge.meta.node
import hep.dataforge.meta.toMetaItem
import kotlin.test.Test import kotlin.test.Test
import kotlin.test.assertEquals import kotlin.test.assertEquals
@ -26,9 +27,9 @@ class ConvexTest {
val convex = group.first() as Convex val convex = group.first() as Convex
val json = Visual3D.json.toJson(Convex.serializer(), 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, points.count())
assertEquals(8, convex.points.size) assertEquals(8, convex.points.size)

View File

@ -1,7 +1,7 @@
package hep.dataforge.vis.spatial package hep.dataforge.vis.spatial
import hep.dataforge.vis.common.Colors import hep.dataforge.vis.Colors
import hep.dataforge.vis.common.get import hep.dataforge.vis.get
import kotlin.math.PI import kotlin.math.PI
import kotlin.test.Test import kotlin.test.Test
import kotlin.test.assertEquals import kotlin.test.assertEquals

View File

@ -3,7 +3,7 @@ package hep.dataforge.vis.spatial
import hep.dataforge.meta.int import hep.dataforge.meta.int
import hep.dataforge.meta.set import hep.dataforge.meta.set
import hep.dataforge.names.asName import hep.dataforge.names.asName
import hep.dataforge.vis.common.useStyle import hep.dataforge.vis.useStyle
import kotlin.test.Test import kotlin.test.Test
import kotlin.test.assertEquals import kotlin.test.assertEquals

View File

@ -1,12 +1,12 @@
package hep.dataforge.vis.spatial package hep.dataforge.vis.spatial
import hep.dataforge.vis.spatial.Visual3D.Companion.json import hep.dataforge.names.toName
import kotlinx.serialization.ImplicitReflectionSerializer import hep.dataforge.vis.VisualObject
import hep.dataforge.vis.get
import kotlin.test.Test import kotlin.test.Test
import kotlin.test.assertEquals import kotlin.test.assertEquals
class SerializationTest { class SerializationTest {
@ImplicitReflectionSerializer
@Test @Test
fun testCubeSerialization() { fun testCubeSerialization() {
val cube = Box(100f, 100f, 100f).apply { val cube = Box(100f, 100f, 100f).apply {
@ -14,9 +14,30 @@ class SerializationTest {
x = 100 x = 100
z = -100 z = -100
} }
val string = json.stringify(Box.serializer(), cube) val string = cube.stringify()
println(string) println(string)
val newCube = json.parse(Box.serializer(), string) val newCube = VisualObject.parseJson(string)
assertEquals(cube.config, newCube.config) 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)
}
} }

View File

@ -2,17 +2,17 @@ package hep.dataforge.vis.spatial.three
import hep.dataforge.context.Context import hep.dataforge.context.Context
import hep.dataforge.meta.Meta import hep.dataforge.meta.Meta
import hep.dataforge.meta.get import hep.dataforge.meta.getProperty
import hep.dataforge.meta.string import hep.dataforge.meta.string
import hep.dataforge.names.Name import hep.dataforge.names.Name
import hep.dataforge.names.plus import hep.dataforge.names.plus
import hep.dataforge.names.toName import hep.dataforge.names.toName
import hep.dataforge.output.Renderer 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.VisualObject3D
import hep.dataforge.vis.spatial.specifications.CameraSpec import hep.dataforge.vis.spatial.specifications.Camera
import hep.dataforge.vis.spatial.specifications.CanvasSpec import hep.dataforge.vis.spatial.specifications.Canvas
import hep.dataforge.vis.spatial.specifications.ControlsSpec import hep.dataforge.vis.spatial.specifications.Controls
import hep.dataforge.vis.spatial.three.ThreeMaterials.HIGHLIGHT_MATERIAL import hep.dataforge.vis.spatial.three.ThreeMaterials.HIGHLIGHT_MATERIAL
import info.laht.threekt.WebGLRenderer import info.laht.threekt.WebGLRenderer
import info.laht.threekt.cameras.PerspectiveCamera 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<VisualObject3D> { class ThreeCanvas(element: HTMLElement, val three: ThreePlugin, val canvas: Canvas) : Renderer<VisualObject3D> {
override val context: Context get() = three.context 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 var clickListener: ((Name) -> Unit)? = null
val axes = AxesHelper(spec.axes.size.toInt()).apply { val axes = AxesHelper(canvas.axes.size.toInt()).apply {
visible = spec.axes.visible visible = canvas.axes.visible
} }
val scene: Scene = Scene().apply { val scene: Scene = Scene().apply {
add(axes) add(axes)
} }
val camera = buildCamera(spec.camera) val camera = buildCamera(canvas.camera)
init { init {
element.clear() 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() { fun animate() {
val mesh = pick() val mesh = pick()
@ -108,7 +108,7 @@ class ThreeCanvas(element: HTMLElement, val three: ThreePlugin, val spec: Canvas
element.appendChild(renderer.domElement) 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 = { element.onresize = {
renderer.setSize(element.offsetWidth, element.offsetWidth) 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, spec.fov,
1.0, 1.0,
spec.nearClip, 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)) translateZ(spec.distance * sin(spec.zenith) * cos(spec.azimuth))
} }
private fun addControls(element: Node, controlsSpec: ControlsSpec) { private fun addControls(element: Node, controls: Controls) {
when (controlsSpec["type"].string) { when (controls.getProperty("type").string) {
"trackball" -> TrackballControls(camera, element) "trackball" -> TrackballControls(camera, element)
else -> OrbitControls(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 = fun ThreePlugin.output(element: HTMLElement, spec: Canvas = Canvas.empty()): ThreeCanvas =
ThreeCanvas(element, this, spec) ThreeCanvas(element, this, spec)
fun ThreePlugin.render(element: HTMLElement, obj: VisualObject3D, spec: Canvas = Canvas.empty()): Unit =
output(element, spec).render(obj)

View File

@ -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<ThreeCanvasProps, RState>() {
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)
}
}
}

View File

@ -3,7 +3,7 @@ package hep.dataforge.vis.spatial.three
import hep.dataforge.names.Name import hep.dataforge.names.Name
import hep.dataforge.names.startsWith import hep.dataforge.names.startsWith
import hep.dataforge.provider.Type 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.*
import hep.dataforge.vis.spatial.Material3D.Companion.MATERIAL_KEY import hep.dataforge.vis.spatial.Material3D.Companion.MATERIAL_KEY
import hep.dataforge.vis.spatial.three.ThreeFactory.Companion.TYPE import hep.dataforge.vis.spatial.three.ThreeFactory.Companion.TYPE

View File

@ -2,8 +2,8 @@ package hep.dataforge.vis.spatial.three
import hep.dataforge.meta.* import hep.dataforge.meta.*
import hep.dataforge.values.ValueType import hep.dataforge.values.ValueType
import hep.dataforge.vis.common.Colors import hep.dataforge.vis.Colors
import hep.dataforge.vis.common.VisualObject import hep.dataforge.vis.VisualObject
import hep.dataforge.vis.spatial.Material3D import hep.dataforge.vis.spatial.Material3D
import info.laht.threekt.materials.LineBasicMaterial import info.laht.threekt.materials.LineBasicMaterial
import info.laht.threekt.materials.Material import info.laht.threekt.materials.Material

View File

@ -3,7 +3,7 @@ package hep.dataforge.vis.spatial.three
import hep.dataforge.context.* import hep.dataforge.context.*
import hep.dataforge.meta.Meta import hep.dataforge.meta.Meta
import hep.dataforge.names.* import hep.dataforge.names.*
import hep.dataforge.vis.common.VisualObject import hep.dataforge.vis.VisualObject
import hep.dataforge.vis.spatial.* import hep.dataforge.vis.spatial.*
import info.laht.threekt.core.Object3D import info.laht.threekt.core.Object3D
import kotlin.collections.set import kotlin.collections.set

View File

@ -2,9 +2,8 @@
package hep.dataforge.vis.spatial.three package hep.dataforge.vis.spatial.three
import hep.dataforge.io.serialization.ConfigSerializer
import hep.dataforge.meta.Config 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.Point3D
import hep.dataforge.vis.spatial.Point3DSerializer import hep.dataforge.vis.spatial.Point3DSerializer
import hep.dataforge.vis.spatial.VisualObject3D import hep.dataforge.vis.spatial.VisualObject3D
@ -26,7 +25,6 @@ class CustomThreeVisualObject(val threeFactory: ThreeFactory<VisualObject3D>) :
override var rotation: Point3D? = null override var rotation: Point3D? = null
override var scale: Point3D? = null override var scale: Point3D? = null
@Serializable(ConfigSerializer::class)
override var properties: Config? = null override var properties: Config? = null
override fun toObject3D(): Object3D = threeFactory(this) override fun toObject3D(): Object3D = threeFactory(this)

View File

@ -1,4 +1,4 @@
@file:JsModule("@hi-level/three-csg") @file:JsModule("three-csg-ts")
@file:JsNonModule @file:JsNonModule
@file:Suppress( @file:Suppress(
"INTERFACE_WITH_SUPERCLASS", "INTERFACE_WITH_SUPERCLASS",

View File

@ -1,7 +1,7 @@
package hep.dataforge.vis.spatial.three package hep.dataforge.vis.spatial.three
import hep.dataforge.js.requireJS 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.Visual3D
import hep.dataforge.vis.spatial.VisualGroup3D import hep.dataforge.vis.spatial.VisualGroup3D
import kotlinx.html.InputType import kotlinx.html.InputType

View File

@ -5,7 +5,7 @@ import hep.dataforge.context.ContextAware
import hep.dataforge.meta.Meta import hep.dataforge.meta.Meta
import hep.dataforge.output.Renderer import hep.dataforge.output.Renderer
import hep.dataforge.vis.spatial.VisualObject3D 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.application.Platform
import javafx.beans.property.ObjectProperty import javafx.beans.property.ObjectProperty
import javafx.beans.property.SimpleObjectProperty import javafx.beans.property.SimpleObjectProperty
@ -14,7 +14,7 @@ import javafx.scene.paint.Color
import org.fxyz3d.scene.Axes import org.fxyz3d.scene.Axes
import tornadofx.* import tornadofx.*
class FXCanvas3D(val plugin: FX3DPlugin, val spec: CanvasSpec = CanvasSpec.empty()) : class FXCanvas3D(val plugin: FX3DPlugin, val spec: Canvas = Canvas.empty()) :
Fragment(), Renderer<VisualObject3D>, ContextAware { Fragment(), Renderer<VisualObject3D>, ContextAware {
override val context: Context get() = plugin.context override val context: Context get() = plugin.context

View File

@ -5,7 +5,7 @@ import hep.dataforge.meta.double
import hep.dataforge.meta.get import hep.dataforge.meta.get
import hep.dataforge.meta.int import hep.dataforge.meta.int
import hep.dataforge.values.ValueType import hep.dataforge.values.ValueType
import hep.dataforge.vis.common.Colors import hep.dataforge.vis.Colors
import hep.dataforge.vis.spatial.Material3D import hep.dataforge.vis.spatial.Material3D
import javafx.scene.paint.Color import javafx.scene.paint.Color
import javafx.scene.paint.Material import javafx.scene.paint.Material

View File

@ -3,7 +3,7 @@ package hep.dataforge.vis.spatial.fx
import hep.dataforge.names.Name import hep.dataforge.names.Name
import hep.dataforge.names.isEmpty import hep.dataforge.names.isEmpty
import hep.dataforge.names.toName import hep.dataforge.names.toName
import hep.dataforge.vis.common.VisualObject import hep.dataforge.vis.VisualObject
import hep.dataforge.vis.spatial.Proxy import hep.dataforge.vis.spatial.Proxy
import javafx.scene.Group import javafx.scene.Group
import javafx.scene.Node import javafx.scene.Node

View File

@ -1,6 +1,5 @@
package hep.dataforge.vis.spatial.fx package hep.dataforge.vis.spatial.fx
import hep.dataforge.vis.spatial.specifications.CameraSpec
import javafx.beans.InvalidationListener import javafx.beans.InvalidationListener
import javafx.beans.property.SimpleDoubleProperty import javafx.beans.property.SimpleDoubleProperty
import javafx.event.EventHandler import javafx.event.EventHandler
@ -15,6 +14,7 @@ import javafx.scene.transform.Rotate
import javafx.scene.transform.Translate import javafx.scene.transform.Translate
import tornadofx.* import tornadofx.*
import kotlin.math.* import kotlin.math.*
import hep.dataforge.vis.spatial.specifications.Camera as CameraSpec
class OrbitControls internal constructor(camera: Camera, canvas: SubScene, spec: CameraSpec) { class OrbitControls internal constructor(camera: Camera, canvas: SubScene, spec: CameraSpec) {

View File

@ -4,7 +4,7 @@ import hep.dataforge.meta.*
import hep.dataforge.names.Name import hep.dataforge.names.Name
import hep.dataforge.names.startsWith import hep.dataforge.names.startsWith
import hep.dataforge.names.toName import hep.dataforge.names.toName
import hep.dataforge.vis.common.VisualObject import hep.dataforge.vis.VisualObject
import javafx.application.Platform import javafx.application.Platform
import javafx.beans.binding.ObjectBinding import javafx.beans.binding.ObjectBinding
import tornadofx.* import tornadofx.*

View File

@ -1,23 +1,24 @@
package hep.dataforge.vis.spatial.gdml package hep.dataforge.vis.spatial
import hep.dataforge.meta.Meta import hep.dataforge.meta.JSON_PRETTY
import hep.dataforge.vis.spatial.*
import kotlinx.serialization.* import kotlinx.serialization.*
import kotlinx.serialization.json.* import kotlinx.serialization.json.*
import kotlinx.serialization.modules.SerialModule import kotlinx.serialization.modules.SerialModule
import kotlinx.serialization.modules.SerialModuleCollector import kotlinx.serialization.modules.SerialModuleCollector
import kotlin.reflect.KClass import kotlin.reflect.KClass
internal val SerialDescriptor.jsonType private fun SerialDescriptor.getJsonType() = when (this.kind) {
get() = when (this.kind) { StructureKind.LIST -> "array"
StructureKind.LIST -> "array" PrimitiveKind.BYTE, PrimitiveKind.SHORT, PrimitiveKind.INT, PrimitiveKind.LONG,
PrimitiveKind.BYTE, PrimitiveKind.SHORT, PrimitiveKind.INT, PrimitiveKind.LONG, PrimitiveKind.FLOAT, PrimitiveKind.DOUBLE -> "number"
PrimitiveKind.FLOAT, PrimitiveKind.DOUBLE -> "number" PrimitiveKind.STRING, PrimitiveKind.CHAR, UnionKind.ENUM_KIND -> "string"
PrimitiveKind.STRING, PrimitiveKind.CHAR, UnionKind.ENUM_KIND -> "string" PrimitiveKind.BOOLEAN -> "boolean"
PrimitiveKind.BOOLEAN -> "boolean" else -> "object"
else -> "object" }
}
private fun SerialDescriptor.isVisualObject() = serialName.startsWith("3d")||serialName.startsWith("group")
private const val definitionNode = "\$defs"
private fun SerialModule.enumerate(type: KClass<*>): Sequence<SerialDescriptor> { private fun SerialModule.enumerate(type: KClass<*>): Sequence<SerialDescriptor> {
val list = ArrayList<SerialDescriptor>() val list = ArrayList<SerialDescriptor>()
@ -60,13 +61,16 @@ private fun SerialModule.enumerate(type: KClass<*>): Sequence<SerialDescriptor>
*/ */
private fun jsonSchema(descriptor: SerialDescriptor, context: SerialModule): JsonObject { 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.Point3D?",
"hep.dataforge.vis.spatial.Point2D", "hep.dataforge.vis.spatial.Point2D",
Meta::class.qualifiedName "hep.dataforge.vis.spatial.Point2D?",
"hep.dataforge.meta.Meta",
"hep.dataforge.meta.Meta?"
) )
) return json { ) 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 -> if (!isEnum && !isPolymorphic) descriptor.elementDescriptors().forEachIndexed { index, child ->
val elementName = descriptor.getElementName(index) val elementName = descriptor.getElementName(index)
properties[elementName] = when (elementName) { val elementSchema = when (elementName) {
"templates" -> json { "properties" -> json {
"\$ref" to "#/definitions/hep.dataforge.vis.spatial.VisualGroup3D" "\$ref" to "#/$definitionNode/hep.dataforge.meta.Meta"
} }
"properties" -> json { "first", "second" -> json {
"\$ref" to "#/definitions/${Meta::class.qualifiedName}" "\$ref" to "#/$definitionNode/children"
}
"first", "second" -> json{
"\$ref" to "#/definitions/children"
} }
"styleSheet" -> json { "styleSheet" -> json {
"type" to "object" "type" to "object"
"additionalProperties" to json { "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" "type" to "object"
"additionalProperties" to json { "additionalProperties" to json {
"\$ref" to "#/definitions/children" "\$ref" to "#/$definitionNode/children"
} }
} }
else -> jsonSchema(child, context) else -> jsonSchema(child, context)
} }
properties[elementName] = elementSchema
if (!descriptor.isElementOptional(index)) requiredProperties.add(elementName) if (!descriptor.isElementOptional(index)) requiredProperties.add(elementName)
} }
val jsonType = descriptor.jsonType val jsonType = descriptor.getJsonType()
val objectData: MutableMap<String, JsonElement> = mutableMapOf( val objectData: MutableMap<String, JsonElement> = mutableMapOf(
"description" to JsonLiteral(descriptor.name), "description" to JsonLiteral(descriptor.serialName),
"type" to JsonLiteral(jsonType) "type" to JsonLiteral(jsonType)
) )
if (isEnum) { if (isEnum) {
@ -118,6 +120,11 @@ private fun jsonSchema(descriptor: SerialDescriptor, context: SerialModule): Jso
} }
when (jsonType) { when (jsonType) {
"object" -> { "object" -> {
if(descriptor.isVisualObject()) {
properties["type"] = json {
"const" to descriptor.serialName
}
}
objectData["properties"] = JsonObject(properties) objectData["properties"] = JsonObject(properties)
val required = requiredProperties.map { JsonLiteral(it) } val required = requiredProperties.map { JsonLiteral(it) }
if (required.isNotEmpty()) { if (required.isNotEmpty()) {
@ -140,9 +147,9 @@ fun main() {
"children" to json { "children" to json {
"anyOf" to jsonArray { "anyOf" to jsonArray {
context.enumerate(VisualObject3D::class).forEach { context.enumerate(VisualObject3D::class).forEach {
if (it.name == "hep.dataforge.vis.spatial.VisualGroup3D") { if (it.serialName == "hep.dataforge.vis.spatial.VisualGroup3D") {
+json { +json {
"\$ref" to "#/definitions/${it.name}" "\$ref" to "#/$definitionNode/${it.serialName}"
} }
} else { } else {
+jsonSchema(it, context) +jsonSchema(it, context)
@ -150,18 +157,47 @@ fun main() {
} }
} }
} }
"hep.dataforge.vis.spatial.Point3D" to jsonSchema(Point3DSerializer.descriptor, context) "hep.dataforge.meta.Meta" to json {
"hep.dataforge.vis.spatial.Point2D" to jsonSchema(Point2DSerializer.descriptor, context) "type" to "object"
"hep.dataforge.vis.spatial.VisualGroup3D" to jsonSchema(VisualGroup3D.serializer().descriptor, context) }
"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( println(
Json.indented.stringify( JSON_PRETTY.stringify(
JsonObjectSerializer, JsonObjectSerializer,
json { json {
"definitions" to definitions "\$defs" to definitions
"\$ref" to "#/definitions/hep.dataforge.vis.spatial.VisualGroup3D" "\$ref" to "#/$definitionNode/hep.dataforge.vis.spatial.VisualGroup3D"
} }
) )
) )

View File

@ -1,11 +1,15 @@
import org.openjfx.gradle.JavaFXOptions import scientifik.DependencyConfiguration
import scientifik.FXModule
import scientifik.fx
plugins { plugins {
id("scientifik.mpp") id("scientifik.mpp")
id("org.openjfx.javafxplugin")
id("application") id("application")
} }
val fxVersion: String by rootProject.extra
fx(FXModule.CONTROLS, version = fxVersion, configuration = DependencyConfiguration.IMPLEMENTATION)
kotlin { kotlin {
jvm { jvm {
@ -27,18 +31,9 @@ kotlin {
api(project(":dataforge-vis-spatial-gdml")) api(project(":dataforge-vis-spatial-gdml"))
} }
} }
jvmMain{
dependencies {
api("org.fxyz3d:fxyz3d:0.5.2")
}
}
} }
} }
application { application {
mainClassName = "hep.dataforge.vis.spatial.gdml.demo.GDMLDemoAppKt" mainClassName = "hep.dataforge.vis.spatial.gdml.demo.GDMLDemoAppKt"
}
configure<JavaFXOptions> {
modules("javafx.controls")
} }

View File

@ -1,7 +1,9 @@
package hep.dataforge.vis.spatial.gdml package hep.dataforge.vis.spatial.gdml
import hep.dataforge.meta.setProperty
import hep.dataforge.meta.string import hep.dataforge.meta.string
import hep.dataforge.names.toName import hep.dataforge.names.toName
import hep.dataforge.values.asValue
import hep.dataforge.vis.spatial.Material3D import hep.dataforge.vis.spatial.Material3D
import hep.dataforge.vis.spatial.gdml.demo.cubes import hep.dataforge.vis.spatial.gdml.demo.cubes
import kotlin.test.Test import kotlin.test.Test
@ -12,7 +14,7 @@ class GDMLVisualTest {
fun testPrototypeProperty() { fun testPrototypeProperty() {
val gdml = cubes() val gdml = cubes()
val visual = gdml.toVisual() 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) assertEquals("red", visual["composite000.segment0".toName()]?.getProperty(Material3D.MATERIAL_COLOR_KEY).string)
} }
} }

View File

@ -3,14 +3,12 @@ package hep.dataforge.vis.spatial.gdml.demo
import hep.dataforge.context.Global import hep.dataforge.context.Global
import hep.dataforge.js.Application import hep.dataforge.js.Application
import hep.dataforge.js.startApplication import hep.dataforge.js.startApplication
import hep.dataforge.meta.buildMeta
import hep.dataforge.meta.withBottom
import hep.dataforge.names.Name import hep.dataforge.names.Name
import hep.dataforge.names.isEmpty import hep.dataforge.names.isEmpty
import hep.dataforge.vis.common.VisualGroup import hep.dataforge.vis.VisualGroup
import hep.dataforge.vis.common.VisualObject import hep.dataforge.vis.VisualObject
import hep.dataforge.vis.js.editor.displayObjectTree import hep.dataforge.vis.editor.objectTree
import hep.dataforge.vis.js.editor.displayPropertyEditor import hep.dataforge.vis.editor.visualPropertyEditor
import hep.dataforge.vis.spatial.Material3D.Companion.MATERIAL_COLOR_KEY 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_OPACITY_KEY
import hep.dataforge.vis.spatial.Material3D.Companion.MATERIAL_WIREFRAME_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.ThreePlugin
import hep.dataforge.vis.spatial.three.displayCanvasControls import hep.dataforge.vis.spatial.three.displayCanvasControls
import hep.dataforge.vis.spatial.three.output import hep.dataforge.vis.spatial.three.output
import hep.dataforge.vis.spatial.visible
import org.w3c.dom.* import org.w3c.dom.*
import org.w3c.files.FileList import org.w3c.files.FileList
import org.w3c.files.FileReader import org.w3c.files.FileReader
@ -139,7 +136,7 @@ private class GDMLDemoApp : Application {
message("Converting GDML into DF-VIS format") message("Converting GDML into DF-VIS format")
gdml.toVisual(gdmlConfiguration) gdml.toVisual(gdmlConfiguration)
} }
name.endsWith(".json") -> VisualGroup3D.fromJson(data) name.endsWith(".json") -> VisualGroup3D.parseJson(data)
else -> { else -> {
window.alert("File extension is not recognized: $name") window.alert("File extension is not recognized: $name")
error("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 visual is VisualGroup -> visual[name] ?: return
else -> return else -> return
} }
editorElement.displayPropertyEditor(name, child) { item ->
//val descriptorMeta = Material3D.descriptor
val properties = item.allProperties() editorElement.visualPropertyEditor(name, child) {
val bottom = buildMeta { VISIBLE_KEY put true
VISIBLE_KEY put (item.visible ?: true) if (child is VisualObject3D) {
if (item is VisualObject3D) { MATERIAL_COLOR_KEY put "#ffffff"
MATERIAL_COLOR_KEY put "#ffffff" MATERIAL_OPACITY_KEY put 1.0
MATERIAL_OPACITY_KEY put 1.0 MATERIAL_WIREFRAME_KEY put false
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 // canvas.clickListener = ::selectElement
//tree.visualObjectTree(visual, editor::propertyEditor) //tree.visualObjectTree(visual, editor::propertyEditor)
treeElement.displayObjectTree(visual) { treeName -> treeElement.objectTree(visual) { treeName ->
selectElement(treeName) selectElement(treeName)
canvas.highlight(treeName) canvas.highlight(treeName)
} }
canvas.render(visual)
canvas.render(visual) canvas.render(visual)
message(null) message(null)
spinner(false) spinner(false)

View File

Before

Width:  |  Height:  |  Size: 31 KiB

After

Width:  |  Height:  |  Size: 31 KiB

View File

@ -1,8 +1,8 @@
package hep.dataforge.vis.spatial.gdml.demo package hep.dataforge.vis.spatial.gdml.demo
import hep.dataforge.context.Global import hep.dataforge.context.Global
import hep.dataforge.vis.fx.editor.VisualObjectEditorFragment import hep.dataforge.vis.editor.VisualObjectEditorFragment
import hep.dataforge.vis.fx.editor.VisualObjectTreeFragment import hep.dataforge.vis.editor.VisualObjectTreeFragment
import hep.dataforge.vis.spatial.Material3D import hep.dataforge.vis.spatial.Material3D
import hep.dataforge.vis.spatial.Visual3D import hep.dataforge.vis.spatial.Visual3D
import hep.dataforge.vis.spatial.VisualGroup3D import hep.dataforge.vis.spatial.VisualGroup3D

View File

@ -1,5 +1,7 @@
package hep.dataforge.vis.spatial.gdml.demo 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.Material3D
import hep.dataforge.vis.spatial.Visual3D import hep.dataforge.vis.spatial.Visual3D
import hep.dataforge.vis.spatial.VisualGroup3D import hep.dataforge.vis.spatial.VisualGroup3D
@ -18,7 +20,7 @@ fun Visual3D.Companion.readFile(file: File): VisualGroup3D = when {
solidConfiguration = { parent, solid -> solidConfiguration = { parent, solid ->
if (solid.name == "cave") { if (solid.name == "cave") {
setProperty(Material3D.MATERIAL_WIREFRAME_KEY, true) setProperty(Material3D.MATERIAL_WIREFRAME_KEY, true.asValue())
} }
if (parent.physVolumes.isNotEmpty()) { if (parent.physVolumes.isNotEmpty()) {
useStyle("opaque") { 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.name.endsWith("json.zip") -> {
file.inputStream().use { file.inputStream().use {
val unzip = ZipInputStream(it, Charsets.UTF_8) val unzip = ZipInputStream(it, Charsets.UTF_8)
val text = unzip.readAllBytes().decodeToString() val text = unzip.readBytes().decodeToString()
VisualGroup3D.fromJson(text) VisualGroup3D.parseJson(text)
} }
} }
file.name.endsWith("json.gz") -> { file.name.endsWith("json.gz") -> {
file.inputStream().use { file.inputStream().use {
val unzip = GZIPInputStream(it) val unzip = GZIPInputStream(it)
val text = unzip.readAllBytes().decodeToString() val text = unzip.readBytes().decodeToString()
VisualGroup3D.fromJson(text) VisualGroup3D.parseJson(text)
} }
} }
else -> error("Unknown extension ${file.extension}") else -> error("Unknown extension ${file.extension}")

View File

@ -5,6 +5,7 @@ import hep.dataforge.vis.spatial.VisualGroup3D
import hep.dataforge.vis.spatial.gdml.LUnit import hep.dataforge.vis.spatial.gdml.LUnit
import hep.dataforge.vis.spatial.gdml.readFile import hep.dataforge.vis.spatial.gdml.readFile
import hep.dataforge.vis.spatial.gdml.toVisual import hep.dataforge.vis.spatial.gdml.toVisual
import hep.dataforge.vis.spatial.stringify
import scientifik.gdml.GDML import scientifik.gdml.GDML
import java.io.File import java.io.File
import java.nio.file.Paths import java.nio.file.Paths
@ -14,6 +15,6 @@ fun main() {
val visual = gdml.toVisual { val visual = gdml.toVisual {
lUnit = LUnit.CM 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) File("D:\\Work\\Projects\\gdml.kt\\gdml-source\\cubes.json").writeText(json)
} }

View File

@ -1,15 +1,15 @@
package hep.dataforge.vis.spatial package hep.dataforge.vis.spatial
import hep.dataforge.names.asName import hep.dataforge.names.asName
import org.junit.Test import org.junit.jupiter.api.Test
import kotlin.test.Ignore import kotlin.test.Ignore
class FileSerializationTest { class FileSerializationTest {
@Test @Test
@Ignore @Ignore
fun testFileRead(){ fun testFileRead(){
val text = this::class.java.getResourceAsStream("/cubes.json").readAllBytes().decodeToString() val text = this::class.java.getResourceAsStream("/cubes.json").readBytes().decodeToString()
val visual = VisualGroup3D.fromJson(text) val visual = VisualGroup3D.parseJson(text)
visual["composite_001".asName()] visual["composite_001".asName()]
} }
} }

View File

@ -1,36 +1,25 @@
import scientifik.useSerialization import scientifik.jsDistDirectory
plugins { plugins {
id("scientifik.mpp") id("scientifik.mpp")
//id("org.openjfx.javafxplugin")
id("application") id("application")
} }
group = "ru.mipt.npm" group = "ru.mipt.npm"
useSerialization() val ktorVersion = "1.3.2"
val ktor_version = "1.3.0-rc"
kotlin { kotlin {
js { val installJS = tasks.getByName("jsBrowserDistribution")
browser {
webpackTask {
sourceMaps = true
}
}
}
val installJS = tasks.getByName<Copy>("installJsDist")
jvm { jvm {
withJava() withJava()
compilations.findByName("main").apply { compilations.findByName("jvmMain").apply {
tasks.getByName<ProcessResources>("jvmProcessResources") { tasks.getByName<ProcessResources>("jvmProcessResources") {
dependsOn(installJS) dependsOn(installJS)
afterEvaluate { afterEvaluate {
from(installJS.destinationDir) from(project.jsDistDirectory)
} }
} }
} }
@ -45,23 +34,29 @@ kotlin {
jvmMain { jvmMain {
dependencies { dependencies {
implementation("org.apache.commons:commons-math3:3.6.1") implementation("org.apache.commons:commons-math3:3.6.1")
implementation("io.ktor:ktor-server-cio:$ktor_version") implementation("io.ktor:ktor-server-cio:$ktorVersion")
implementation("io.ktor:ktor-serialization:$ktor_version") implementation("io.ktor:ktor-serialization:$ktorVersion")
} }
} }
jsMain{ jsMain {
dependencies{ dependencies {
implementation("io.ktor:ktor-client-js:$ktor_version") implementation("io.ktor:ktor-client-js:$ktorVersion")
implementation("io.ktor:ktor-client-serialization-js:$ktor_version") implementation("io.ktor:ktor-client-serialization-js:$ktorVersion")
implementation(npm("text-encoding")) implementation(npm("text-encoding"))
implementation(npm("abort-controller")) 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 { application {
mainClassName = "ru.mipt.npm.muon.monitor.server/MMServerKt" mainClassName = "ru.mipt.npm.muon.monitor.server.MMServerKt"
} }
//configure<JavaFXOptions> { //configure<JavaFXOptions> {

Some files were not shown because too many files have changed in this diff Show More