Dev #24

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

View File

@ -1,50 +1,49 @@
import org.openjfx.gradle.JavaFXOptions
import scientifik.useSerialization
plugins {
id("scientifik.mpp")
id("org.openjfx.javafxplugin")
}
val dataforgeVersion: String by rootProject.extra
//val kvisionVersion: String by rootProject.extra("2.0.0-M1")
useSerialization()
kotlin {
jvm{
withJava()
}
sourceSets {
commonMain{
commonMain {
dependencies {
api("hep.dataforge:dataforge-output:$dataforgeVersion")
}
}
jvmMain{
jvmMain {
dependencies {
api("no.tornado:tornadofx:1.7.19")
api("no.tornado:tornadofx:1.7.20")
//api("no.tornado:tornadofx-controlsfx:0.1.1")
api("de.jensd:fontawesomefx-fontawesome:4.7.0-11"){
api("de.jensd:fontawesomefx-fontawesome:4.7.0-11") {
exclude(group = "org.openjfx")
}
api("de.jensd:fontawesomefx-commons:11.0"){
api("de.jensd:fontawesomefx-commons:11.0") {
exclude(group = "org.openjfx")
}
}
}
jsMain{
jsMain {
dependencies {
api("hep.dataforge:dataforge-output-html:$dataforgeVersion")
//api(npm("bootstrap","4.4.1"))
implementation(npm("jsoneditor"))
implementation(npm("file-saver"))
//React, React DOM + Wrappers (chapter 3)
api("org.jetbrains:kotlin-react:16.13.0-pre.94-kotlin-1.3.70")
api("org.jetbrains:kotlin-react-dom:16.13.0-pre.94-kotlin-1.3.70")
api(npm("react", "16.13.0"))
api(npm("react-dom", "16.13.0"))
//Kotlin Styled (chapter 3)
api("org.jetbrains:kotlin-styled:1.0.0-pre.94-kotlin-1.3.70")
api(npm("styled-components"))
api(npm("inline-style-prefixer"))
api(npm("bootstrap","4.3.1"))
//api(npm("jsoneditor", "8.6.1"))
api(npm("file-saver","2.0.2"))
}
}
}
}
configure<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.names.Name
@ -20,6 +20,17 @@ abstract class AbstractVisualGroup : AbstractVisualObject(), MutableVisualGroup
*/
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<*>?) {
super.propertyChanged(name, before, after)
forEach {
@ -37,7 +48,12 @@ abstract class AbstractVisualGroup : AbstractVisualObject(), MutableVisualGroup
* Add listener for children change
*/
override fun onChildrenChange(owner: Any?, action: (Name, VisualObject?) -> Unit) {
structureChangeListeners.add(StructureChangeListeners(owner, action))
structureChangeListeners.add(
StructureChangeListeners(
owner,
action
)
)
}
/**
@ -68,12 +84,41 @@ abstract class AbstractVisualGroup : AbstractVisualObject(), MutableVisualGroup
* Add a static child. Statics could not be found by name, removed or replaced
*/
protected open fun addStatic(child: VisualObject) =
setChild(NameToken("@static(${child.hashCode()})"), child)
set(NameToken("@static(${child.hashCode()})").asName(), child)
protected abstract fun createGroup(): AbstractVisualGroup
/**
* Set this node as parent for given node
*/
protected fun attach(child: VisualObject) {
if (child.parent == null) {
child.parent = this
} else if (child.parent !== this) {
error("Can't reassign existing parent for $child")
}
}
/**
* Recursively create a child group
*/
protected abstract fun createGroup(name: Name): MutableVisualGroup
private fun createGroups(name: Name): AbstractVisualGroup {
return when {
name.isEmpty() -> error("Should be unreachable")
name.length == 1 -> {
val token = name.first()!!
when (val current = children[token]) {
null -> createGroup().also { child ->
attach(child)
setChild(token, child)
}
is AbstractVisualGroup -> current
else -> error("Can't create group with name $name because it exists and not a group")
}
}
else -> createGroups(name.first()!!.asName()).createGroups(name.cutFirst())
}
}
/**
* Add named or unnamed child to the group. If key is null the child is considered unnamed. Both key and value are not
@ -91,16 +136,17 @@ abstract class AbstractVisualGroup : AbstractVisualObject(), MutableVisualGroup
if (child == null) {
removeChild(token)
} else {
attach(child)
setChild(token, child)
}
}
else -> {
//TODO add safety check
val parent = (get(name.cutLast()) as? MutableVisualGroup) ?: createGroup(name.cutLast())
val parent = (get(name.cutLast()) as? MutableVisualGroup) ?: createGroups(name.cutLast())
parent[name.last()!!.asName()] = child
}
}
structureChangeListeners.forEach { it.callback(name, child) }
childrenChanged(name, child)
}
}

View File

@ -1,9 +1,10 @@
package hep.dataforge.vis.common
package hep.dataforge.vis
import hep.dataforge.meta.*
import hep.dataforge.names.Name
import hep.dataforge.names.asName
import hep.dataforge.vis.common.VisualObject.Companion.STYLE_KEY
import hep.dataforge.values.Value
import hep.dataforge.vis.VisualObject.Companion.STYLE_KEY
import kotlinx.serialization.Transient
internal data class PropertyListener(
@ -14,7 +15,7 @@ internal data class PropertyListener(
abstract class AbstractVisualObject : VisualObject {
@Transient
override var parent: VisualObject? = null
override var parent: VisualGroup? = null
protected abstract var properties: Config?
@ -22,7 +23,7 @@ abstract class AbstractVisualObject : VisualObject {
get() = properties?.get(STYLE_KEY).stringList
set(value) {
//val allStyles = (field + value).distinct()
setProperty(STYLE_KEY, value)
setProperty(STYLE_KEY, Value.of(value))
updateStyles(value)
}
@ -66,7 +67,7 @@ abstract class AbstractVisualObject : VisualObject {
private var styleCache: Meta? = null
/**
* Collect all styles for this object in a laminate
* Collect all styles for this object in a single cached meta
*/
protected val mergedStyles: Meta
get() = styleCache ?: findAllStyles().merge().also {

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

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)
package hep.dataforge.vis.common
package hep.dataforge.vis
import hep.dataforge.io.serialization.MetaSerializer
import hep.dataforge.meta.*
import hep.dataforge.names.Name
import hep.dataforge.names.asName
import kotlinx.serialization.*
import kotlinx.serialization.builtins.MapSerializer
import kotlinx.serialization.builtins.serializer
/**
* A container for styles
*/
@Serializable
class StyleSheet() {
class StyleSheet private constructor(private val styleMap: MutableMap<String, Meta> = LinkedHashMap()) {
@Transient
internal var owner: VisualObject? = null
@ -20,12 +21,10 @@ class StyleSheet() {
this.owner = owner
}
private val styleMap = HashMap<String, Meta>()
val items: Map<String, Meta> get() = styleMap
operator fun get(key: String): Meta? {
return styleMap[key] ?: (owner?.parent as? VisualGroup)?.styleSheet?.get(key)
return styleMap[key] ?: owner?.parent?.styleSheet?.get(key)
}
/**
@ -46,20 +45,23 @@ class StyleSheet() {
}
operator fun set(key: String, builder: MetaBuilder.() -> Unit) {
val newStyle = get(key)?.let { buildMeta(it, builder) } ?: buildMeta(builder)
val newStyle = get(key)?.edit(builder) ?: Meta(builder)
set(key, newStyle.seal())
}
companion object: KSerializer<StyleSheet>{
override val descriptor: SerialDescriptor
get() = TODO("Not yet implemented")
@Serializer(StyleSheet::class)
companion object : KSerializer<StyleSheet> {
private val mapSerializer = MapSerializer(String.serializer(), MetaSerializer)
override val descriptor: SerialDescriptor get() = mapSerializer.descriptor
override fun deserialize(decoder: Decoder): StyleSheet {
TODO("Not yet implemented")
val map = mapSerializer.deserialize(decoder)
return StyleSheet(map as? MutableMap<String, Meta> ?: LinkedHashMap(map))
}
override fun serialize(encoder: Encoder, obj: StyleSheet) {
TODO("Not yet implemented")
override fun serialize(encoder: Encoder, value: StyleSheet) {
mapSerializer.serialize(encoder, value.items)
}
}

View File

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

View File

@ -1,4 +1,4 @@
package hep.dataforge.vis.common
package hep.dataforge.vis
import hep.dataforge.names.*
import hep.dataforge.provider.Provider
@ -6,7 +6,8 @@ import hep.dataforge.provider.Provider
/**
* Represents a group of [VisualObject] instances
*/
interface VisualGroup : Provider, Iterable<VisualObject>, VisualObject {
interface VisualGroup : Provider, Iterable<VisualObject>,
VisualObject {
/**
* 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.asName
import hep.dataforge.names.toName
import hep.dataforge.provider.Type
import hep.dataforge.vis.common.VisualObject.Companion.TYPE
import hep.dataforge.vis.VisualObject.Companion.TYPE
import kotlinx.serialization.PolymorphicSerializer
import kotlinx.serialization.Transient
//private fun Laminate.withTop(meta: Meta): Laminate = Laminate(listOf(meta) + layers)
@ -21,24 +25,19 @@ interface VisualObject : Configurable {
* The parent object of this one. If null, this one is a root.
*/
@Transient
var parent: VisualObject?
var parent: VisualGroup?
/**
* All properties including styles and prototypes if present, but without inheritance
*/
fun allProperties(): Laminate
/**
* Set property for this object
*/
fun setProperty(name: Name, value: Any?) {
config[name] = value
}
/**
* Get property including or excluding parent properties
*/
fun getProperty(name: Name, inherit: Boolean = true): MetaItem<*>?
fun getProperty(name: Name, inherit: Boolean): MetaItem<*>?
override fun getProperty(name: Name): MetaItem<*>? = getProperty(name, true)
/**
* Trigger property invalidation event. If [name] is empty, notify that the whole object is changed
@ -66,6 +65,10 @@ interface VisualObject : Configurable {
const val TYPE = "visual"
val STYLE_KEY = "@style".asName()
private val VISUAL_OBJECT_SERIALIZER = PolymorphicSerializer(VisualObject::class)
fun serializer() = VISUAL_OBJECT_SERIALIZER
//const val META_KEY = "@meta"
//const val TAGS_KEY = "@tags"
@ -77,11 +80,6 @@ interface VisualObject : Configurable {
*/
fun VisualObject.getProperty(key: String, inherit: Boolean = true): MetaItem<*>? = getProperty(key.toName(), inherit)
/**
* Set [VisualObject] property using key as a String
*/
fun VisualObject.setProperty(key: String, value: Any?) = setProperty(key.toName(), value)
/**
* Add style name to the list of styles to be resolved later. The style with given name does not necessary exist at the moment.
*/

View File

@ -1,4 +1,4 @@
package hep.dataforge.vis.common
package hep.dataforge.vis
import hep.dataforge.meta.*
import hep.dataforge.names.Name
@ -105,8 +105,8 @@ fun VisualObject.int(default: Int, name: Name? = null, inherited: Boolean = fals
inline fun <reified E : Enum<E>> VisualObject.enum(default: E, name: Name? = null, inherited: Boolean = false) =
VisualObjectDelegateWrapper(this, name, default, inherited) {
item -> item.string?.let { enumValueOf<E>(it) }
VisualObjectDelegateWrapper(this, name, default, inherited) { item ->
item.string?.let { enumValueOf<E>(it) }
}
//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.js.div
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) {
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>) {
div("container-fluid") {
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.plus
import hep.dataforge.vis.common.VisualGroup
import hep.dataforge.vis.common.VisualObject
import hep.dataforge.vis.common.isEmpty
import hep.dataforge.vis.VisualGroup
import hep.dataforge.vis.VisualObject
import hep.dataforge.vis.isEmpty
import kotlinx.html.TagConsumer
import kotlinx.html.dom.append
import kotlinx.html.js.*
@ -13,18 +13,18 @@ import org.w3c.dom.HTMLElement
import org.w3c.dom.HTMLSpanElement
import kotlin.dom.clear
fun Element.displayObjectTree(
obj: VisualObject,
clickCallback: (Name) -> Unit = {}
) {
clear()
append {
card("Object tree") {
subTree(Name.EMPTY, obj, clickCallback)
}
}
}
//fun Element.displayObjectTree(
// obj: VisualObject,
// clickCallback: (Name) -> Unit = {}
//) {
// clear()
// append {
// card("Object tree") {
// subTree(Name.EMPTY, obj, clickCallback)
// }
// }
//}
//
private fun TagConsumer<HTMLElement>.subTree(
name: Name,
obj: VisualObject,

View File

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

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.names.Name

View File

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

View File

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

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

View File

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

View File

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

View File

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

View File

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

View File

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

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

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

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

View File

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

View File

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

View File

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

View File

@ -1,43 +1,29 @@
package hep.dataforge.vis.spatial.gdml
import hep.dataforge.vis.spatial.stringify
import nl.adaptivity.xmlutil.StAXReader
import org.junit.Test
import org.junit.jupiter.api.Test
import scientifik.gdml.GDML
import java.io.File
import java.net.URL
import kotlin.test.Ignore
class TestConvertor {
@Test
@Ignore
fun testBMNGeometry() {
val url = URL("https://drive.google.com/open?id=1w5e7fILMN83JGgB8WANJUYm8OW2s0WVO")
val file = File("D:\\Work\\Projects\\gdml.kt\\gdml-source\\BM@N.gdml")
val stream = if (file.exists()) {
file.inputStream()
} else {
url.openStream()
}
val xmlReader = StAXReader(stream, "UTF-8")
val xml = GDML.format.parse(GDML.serializer(), xmlReader)
xml.toVisual()
}
@Test
@Ignore
fun testCubes() {
val file = File("D:\\Work\\Projects\\gdml.kt\\gdml-source\\cubes.gdml ")
val stream = if (file.exists()) {
file.inputStream()
} else {
return
}
val stream = javaClass.getResourceAsStream("/gdml/BM@N.gdml")
val xmlReader = StAXReader(stream, "UTF-8")
val xml = GDML.format.parse(GDML.serializer(), xmlReader)
val visual = xml.toVisual()
println(visual)
println(visual.stringify())
}
@Test
fun testCubes() {
val stream = javaClass.getResourceAsStream("/gdml/cubes.gdml")
val xmlReader = StAXReader(stream, "UTF-8")
val xml = GDML.format.parse(GDML.serializer(), xmlReader)
val visual = xml.toVisual()
// println(visual)
}
}

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,48 +1,49 @@
@file:UseSerializers(
Point3DSerializer::class,
ConfigSerializer::class,
NameTokenSerializer::class,
NameSerializer::class,
MetaSerializer::class
Point3DSerializer::class
)
package hep.dataforge.vis.spatial
import hep.dataforge.io.serialization.ConfigSerializer
import hep.dataforge.io.serialization.MetaSerializer
import hep.dataforge.io.serialization.NameSerializer
import hep.dataforge.meta.Config
import hep.dataforge.names.Name
import hep.dataforge.names.NameToken
import hep.dataforge.names.asName
import hep.dataforge.names.isEmpty
import hep.dataforge.vis.common.AbstractVisualGroup
import hep.dataforge.vis.common.StyleSheet
import hep.dataforge.vis.common.VisualObject
import hep.dataforge.vis.common.set
import hep.dataforge.vis.*
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import kotlinx.serialization.UseSerializers
import kotlin.collections.set
interface PrototypeHolder {
val parent: VisualGroup?
val prototypes: MutableVisualGroup?
}
/**
* Represents 3-dimensional Visual Group
*/
@Serializable
@SerialName("group.3d")
class VisualGroup3D : AbstractVisualGroup(), VisualObject3D {
class VisualGroup3D : AbstractVisualGroup(), VisualObject3D, PrototypeHolder {
override var styleSheet: StyleSheet? = null
private set
/**
* A container for templates visible inside this group
*/
var prototypes: VisualGroup3D? = null
set(value) {
value?.parent = this
field = value
}
@Serializable(PrototypesSerializer::class)
override var prototypes: MutableVisualGroup? = null
private set
/**
* Create or edit prototype node as a group
*/
fun prototypes(builder: MutableVisualGroup.() -> Unit): Unit {
(prototypes ?: Prototypes().also {
attach(it)
prototypes = it
}).run(builder)
}
//FIXME to be lifted to AbstractVisualGroup after https://github.com/Kotlin/kotlinx.serialization/issues/378 is fixed
override var properties: Config? = null
@ -55,38 +56,18 @@ class VisualGroup3D : AbstractVisualGroup(), VisualObject3D {
private val _children = HashMap<NameToken, VisualObject>()
override val children: Map<NameToken, VisualObject> get() = _children
// init {
// //Do after deserialization
// attachChildren()
// }
override fun attachChildren() {
prototypes?.parent = this
prototypes?.attachChildren()
super.attachChildren()
}
/**
* Update or create stylesheet
*/
fun styleSheet(block: StyleSheet.() -> Unit) {
val res = styleSheet ?: StyleSheet(this).also { styleSheet = it }
res.block()
}
override fun removeChild(token: NameToken) {
_children.remove(token)?.run { parent = null }
childrenChanged(token.asName(), null)
_children.remove(token)?.apply { parent = null }
}
override fun setChild(token: NameToken, child: VisualObject) {
if (child.parent == null) {
child.parent = this
} else if (child.parent !== this) {
error("Can't reassign existing parent for $child")
}
_children[token] = child
childrenChanged(token.asName(), child)
}
// /**
@ -94,25 +75,13 @@ class VisualGroup3D : AbstractVisualGroup(), VisualObject3D {
// */
// override fun addStatic(child: VisualObject) = setChild(NameToken("@static(${child.hashCode()})"), child)
override fun createGroup(name: Name): VisualGroup3D {
return when {
name.isEmpty() -> error("Should be unreachable")
name.length == 1 -> {
val token = name.first()!!
when (val current = children[token]) {
null -> VisualGroup3D().also { setChild(token, it) }
is VisualGroup3D -> current
else -> error("Can't create group with name $name because it exists and not a group")
}
}
else -> createGroup(name.first()!!.asName()).createGroup(name.cutFirst())
}
}
override fun createGroup(): VisualGroup3D = VisualGroup3D()
companion object {
// val PROTOTYPES_KEY = NameToken("@prototypes")
fun fromJson(json: String): VisualGroup3D =
fun parseJson(json: String): VisualGroup3D =
Visual3D.json.parse(serializer(), json).also { it.attachChildren() }
}
}
@ -120,21 +89,50 @@ class VisualGroup3D : AbstractVisualGroup(), VisualObject3D {
/**
* Ger a prototype redirecting the request to the parent if prototype is not found
*/
tailrec fun VisualGroup3D.getPrototype(name: Name): VisualObject3D? =
tailrec fun PrototypeHolder.getPrototype(name: Name): VisualObject3D? =
prototypes?.get(name) as? VisualObject3D ?: (parent as? VisualGroup3D)?.getPrototype(name)
/**
* Create or edit prototype node as a group
* Define a group with given [name], attach it to this parent and return it.
*/
inline fun VisualGroup3D.prototypes(builder: VisualGroup3D.() -> Unit): Unit {
(prototypes ?: VisualGroup3D().also { prototypes = it }).run(builder)
}
/**
* Define a group with given [key], attach it to this parent and return it.
*/
fun VisualGroup3D.group(key: String = "", action: VisualGroup3D.() -> Unit = {}): VisualGroup3D =
fun MutableVisualGroup.group(name: String = "", action: VisualGroup3D.() -> Unit = {}): VisualGroup3D =
VisualGroup3D().apply(action).also {
set(key, it)
set(name, it)
}
internal class Prototypes(
override var children: MutableMap<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
import hep.dataforge.io.serialization.NameSerializer
import hep.dataforge.meta.*
import hep.dataforge.meta.descriptors.NodeDescriptor
import hep.dataforge.names.asName
import hep.dataforge.names.plus
import hep.dataforge.output.Renderer
import hep.dataforge.vis.common.VisualObject
import hep.dataforge.values.ValueType
import hep.dataforge.values.asValue
import hep.dataforge.vis.VisualObject
import hep.dataforge.vis.spatial.VisualObject3D.Companion.DETAIL_KEY
import hep.dataforge.vis.spatial.VisualObject3D.Companion.IGNORE_KEY
import hep.dataforge.vis.spatial.VisualObject3D.Companion.LAYER_KEY
@ -25,7 +27,8 @@ interface VisualObject3D : VisualObject {
companion object {
val VISIBLE_KEY = "visible".asName()
// val SELECTED_KEY = "selected".asName()
// val SELECTED_KEY = "selected".asName()
val DETAIL_KEY = "detail".asName()
val LAYER_KEY = "layer".asName()
val IGNORE_KEY = "ignore".asName()
@ -55,6 +58,22 @@ interface VisualObject3D : VisualObject {
val xScale = scale + x
val yScale = scale + y
val zScale = scale + z
val descriptor by lazy {
NodeDescriptor {
defineValue(VISIBLE_KEY) {
type(ValueType.BOOLEAN)
default(true)
}
defineItem(Material3D.MATERIAL_KEY.toString(), Material3D.descriptor)
// Material3D.MATERIAL_COLOR_KEY put "#ffffff"
// Material3D.MATERIAL_OPACITY_KEY put 1.0
// Material3D.MATERIAL_WIREFRAME_KEY put false
}
}
}
}
@ -64,10 +83,10 @@ interface VisualObject3D : VisualObject {
var VisualObject3D.layer: Int
get() = getProperty(LAYER_KEY).int ?: 0
set(value) {
setProperty(LAYER_KEY, value)
setProperty(LAYER_KEY, value.asValue())
}
fun Renderer<VisualObject3D>.render(meta: Meta = EmptyMeta, action: VisualGroup3D.() -> Unit) =
fun Renderer<VisualObject3D>.render(meta: Meta = Meta.EMPTY, action: VisualGroup3D.() -> Unit) =
render(VisualGroup3D().apply(action), meta)
// Common properties
@ -86,7 +105,7 @@ enum class RotationOrder {
*/
var VisualObject3D.rotationOrder: RotationOrder
get() = getProperty(VisualObject3D.rotationOrder).enum<RotationOrder>() ?: RotationOrder.XYZ
set(value) = setProperty(VisualObject3D.rotationOrder, value.name)
set(value) = setProperty(VisualObject3D.rotationOrder, value.name.asValue())
/**
@ -94,19 +113,19 @@ var VisualObject3D.rotationOrder: RotationOrder
*/
var VisualObject3D.detail: Int?
get() = getProperty(DETAIL_KEY, false).int
set(value) = setProperty(DETAIL_KEY, value)
set(value) = setProperty(DETAIL_KEY, value?.asValue())
var VisualObject.visible: Boolean?
get() = getProperty(VISIBLE_KEY).boolean
set(value) = setProperty(VISIBLE_KEY, value)
set(value) = setProperty(VISIBLE_KEY, value?.asValue())
/**
* If this property is true, the object will be ignored on render.
* Property is not inherited.
*/
var VisualObject.ignore: Boolean?
get() = getProperty(IGNORE_KEY,false).boolean
set(value) = setProperty(IGNORE_KEY, value)
get() = getProperty(IGNORE_KEY, false).boolean
set(value) = setProperty(IGNORE_KEY, value?.asValue())
//var VisualObject.selected: Boolean?
// get() = getProperty(SELECTED_KEY).boolean

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
import hep.dataforge.meta.Meta
import hep.dataforge.meta.buildMeta
import hep.dataforge.meta.get
import hep.dataforge.meta.number
import kotlin.math.PI
object World {
val ZERO = Point3D(0.0, 0.0, 0.0)
val ONE = Point3D(1.0, 1.0, 1.0)
}
const val PI2: Float = 2 * PI.toFloat()
expect class Point2D(x: Number, y: Number) {
var x: Double
@ -13,7 +20,7 @@ expect class Point2D(x: Number, y: Number) {
operator fun Point2D.component1() = x
operator fun Point2D.component2() = y
fun Point2D.toMeta() = buildMeta {
fun Point2D.toMeta() = Meta {
VisualObject3D.x put x
VisualObject3D.y put y
}
@ -34,7 +41,7 @@ operator fun Point3D.component3() = z
fun Meta.point3D() = Point3D(this["x"].number ?: 0, this["y"].number ?: 0, this["y"].number ?: 0)
fun Point3D.toMeta() = buildMeta {
fun Point3D.toMeta() = Meta {
VisualObject3D.x put x
VisualObject3D.y put y
VisualObject3D.z put z

View File

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

View File

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

View File

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

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.names.asName
import hep.dataforge.vis.common.MutableVisualGroup
import hep.dataforge.vis.common.VisualGroup
import hep.dataforge.vis.common.VisualObject
import hep.dataforge.vis.MutableVisualGroup
import hep.dataforge.vis.VisualGroup
import hep.dataforge.vis.VisualObject
import hep.dataforge.vis.spatial.*
internal fun mergeChild(parent: VisualGroup, child: VisualObject): VisualObject {

View File

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

View File

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

View File

@ -1,8 +1,9 @@
package hep.dataforge.vis.spatial
import hep.dataforge.io.toMeta
import hep.dataforge.meta.MetaItem
import hep.dataforge.meta.getIndexed
import hep.dataforge.meta.node
import hep.dataforge.meta.toMetaItem
import kotlin.test.Test
import kotlin.test.assertEquals
@ -26,9 +27,9 @@ class ConvexTest {
val convex = group.first() as Convex
val json = Visual3D.json.toJson(Convex.serializer(), convex)
val meta = json.toMeta()
val meta = json.toMetaItem().node!!
val points = meta.getIndexed("points").values.map { (it as MetaItem.NodeItem<*>).node.point3D()}
val points = meta.getIndexed("points").values.map { (it as MetaItem.NodeItem<*>).node.point3D() }
assertEquals(8, points.count())
assertEquals(8, convex.points.size)

View File

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

View File

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

View File

@ -1,12 +1,12 @@
package hep.dataforge.vis.spatial
import hep.dataforge.vis.spatial.Visual3D.Companion.json
import kotlinx.serialization.ImplicitReflectionSerializer
import hep.dataforge.names.toName
import hep.dataforge.vis.VisualObject
import hep.dataforge.vis.get
import kotlin.test.Test
import kotlin.test.assertEquals
class SerializationTest {
@ImplicitReflectionSerializer
@Test
fun testCubeSerialization() {
val cube = Box(100f, 100f, 100f).apply {
@ -14,9 +14,30 @@ class SerializationTest {
x = 100
z = -100
}
val string = json.stringify(Box.serializer(), cube)
val string = cube.stringify()
println(string)
val newCube = json.parse(Box.serializer(), string)
val newCube = VisualObject.parseJson(string)
assertEquals(cube.config, newCube.config)
}
@Test
fun testProxySerialization() {
val cube = Box(100f, 100f, 100f).apply {
color(222)
x = 100
z = -100
}
val group = VisualGroup3D().apply {
proxy("cube", cube)
proxyGroup("pg", "pg.content".toName()){
sphere(50){
x = -100
}
}
}
val string = group.stringify()
println(string)
val reconstructed = VisualGroup3D.parseJson(string)
assertEquals(group["cube"]?.config, reconstructed["cube"]?.config)
}
}

View File

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

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.startsWith
import hep.dataforge.provider.Type
import hep.dataforge.vis.common.VisualObject
import hep.dataforge.vis.VisualObject
import hep.dataforge.vis.spatial.*
import hep.dataforge.vis.spatial.Material3D.Companion.MATERIAL_KEY
import hep.dataforge.vis.spatial.three.ThreeFactory.Companion.TYPE

View File

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

View File

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

View File

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

View File

@ -1,7 +1,7 @@
package hep.dataforge.vis.spatial.three
import hep.dataforge.js.requireJS
import hep.dataforge.vis.js.editor.accordion
import hep.dataforge.vis.editor.accordion
import hep.dataforge.vis.spatial.Visual3D
import hep.dataforge.vis.spatial.VisualGroup3D
import kotlinx.html.InputType

View File

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

View File

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

View File

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

View File

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

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

View File

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

View File

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

View File

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

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
import hep.dataforge.context.Global
import hep.dataforge.vis.fx.editor.VisualObjectEditorFragment
import hep.dataforge.vis.fx.editor.VisualObjectTreeFragment
import hep.dataforge.vis.editor.VisualObjectEditorFragment
import hep.dataforge.vis.editor.VisualObjectTreeFragment
import hep.dataforge.vis.spatial.Material3D
import hep.dataforge.vis.spatial.Visual3D
import hep.dataforge.vis.spatial.VisualGroup3D

View File

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

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

View File

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

View File

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

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