Code and API cleanup

This commit is contained in:
Alexander Nozik 2020-08-05 15:24:39 +03:00
parent f484d5d1ff
commit 373145b90a
60 changed files with 166 additions and 322 deletions
CHANGELOG.mdREADME.mdbuild.gradle.kts
dataforge-vis-common
dataforge-vis-jsroot/src/main
kotlin/hep/dataforge/vis/jsroot
web
dataforge-vis-spatial-gdml
build.gradle.kts
src/commonMain/kotlin/hep/dataforge/vis/spatial/gdml
dataforge-vis-spatial/src
demo
gdml/src
commonMain/kotlin/hep/dataforge/vis/spatial/gdml/demo
commonTest/kotlin/hep/dataforge/vis/spatial/gdml
jsMain
kotlin/hep/dataforge/vis/spatial/gdml/demo
resources
jvmMain/kotlin/hep/dataforge/vis/spatial/gdml/demo
muon-monitor
build.gradle.kts
src
commonMain/kotlin/ru/mipt/npm/muon/monitor
jsMain
kotlin/ru/mipt/npm/muon/monitor
resources
spatial-showcase/src/jsMain
kotlin/hep/dataforge/vis/spatial/demo
resources
playground/src/jsMain/resources
settings.gradle.kts

0
CHANGELOG.md Normal file

@ -42,7 +42,6 @@ The main framework's features for now include:
- Settings export and import
- Multiple platform support
## About DataForge
DataForge is a software framework for automated scientific data processing. DataForge Visualization
@ -64,7 +63,7 @@ This module is not specific to 3D-visualization.
The `dataforge-vis-common` module also includes configuration editors for JS (in `jsMain`) and JVM (in `jvmMain`).
##### Class diagram:
**Class diagram:**
![](doc/resources/class-diag-common.png)
@ -73,7 +72,7 @@ The `dataforge-vis-common` module also includes configuration editors for JS (in
Includes common classes and serializers for 3D visualization, Three.js and JavaFX implementations.
##### Class diagram:
**Class diagram:**
![](doc/resources/class-diag-3d.png)
@ -125,7 +124,7 @@ Some shapes will also periodically change their color and visibility.
[More details](demo/spatial-showcase/README.md)
##### Example view:
**Example view:**
![](doc/resources/spatial-showcase.png)
@ -137,7 +136,7 @@ A full-stack application example, showing the
[More details](demo/muon-monitor/README.md)
##### Example view:
**Example view:**
![](doc/resources/muon-monitor.png)

@ -1,14 +1,14 @@
import scientifik.useFx
import scientifik.useSerialization
val dataforgeVersion by extra("0.1.8-dev-2")
val dataforgeVersion by extra("0.1.8")
plugins {
val toolsVersion = "0.5.0"
id("scientifik.mpp") version toolsVersion apply false
id("scientifik.jvm") version toolsVersion apply false
id("scientifik.js") version toolsVersion apply false
id("scientifik.publish") version toolsVersion apply false
id("scientifik.mpp") apply false
id("scientifik.jvm") apply false
id("scientifik.js") apply false
id("scientifik.publish") apply false
id("org.jetbrains.changelog") version "0.4.0"
}
allprojects {
@ -16,15 +16,10 @@ allprojects {
mavenLocal()
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/mipt-npm/dataforge")
// maven("https://dl.bintray.com/gbaldeck/kotlin")
// maven("https://dl.bintray.com/rjaros/kotlin")
}
group = "hep.dataforge"
version = "0.1.4-dev"
version = "0.1.4"
}
val githubProject by extra("dataforge-vis")

@ -3,7 +3,6 @@ plugins {
}
val dataforgeVersion: String by rootProject.extra
//val kvisionVersion: String by rootProject.extra("2.0.0-M1")
kotlin {
js {

@ -1,10 +1,9 @@
package hep.dataforge.properties
import hep.dataforge.meta.Config
import hep.dataforge.meta.MetaItem
import hep.dataforge.meta.get
import hep.dataforge.meta.*
import hep.dataforge.names.Name
@DFExperimental
class ConfigProperty(val config: Config, val name: Name) : Property<MetaItem<*>?> {
override var value: MetaItem<*>?
get() = config[name]

@ -11,6 +11,7 @@ import kotlinx.coroutines.launch
//TODO move to core
@DFExperimental
interface Property<T> {
var value: T
@ -18,6 +19,7 @@ interface Property<T> {
fun removeChangeListener(owner: Any? = null)
}
@DFExperimental
@OptIn(ExperimentalCoroutinesApi::class)
fun <T> Property<T>.flow() = callbackFlow<T> {
send(value)
@ -35,6 +37,7 @@ fun <T> Property<T>.flow() = callbackFlow<T> {
*
* @return a mirroring job
*/
@DFExperimental
fun <T> Property<T>.mirror(source: Property<T>, scope: CoroutineScope): Job {
return scope.launch {
source.flow().collect {

@ -33,8 +33,8 @@ abstract class AbstractVisualGroup : AbstractVisualObject(), MutableVisualGroup
override fun propertyChanged(name: Name, before: MetaItem<*>?, after: MetaItem<*>?) {
super.propertyChanged(name, before, after)
forEach {
it.propertyChanged(name, before, after)
for(obj in this) {
obj.propertyChanged(name, before, after)
}
}

@ -19,12 +19,15 @@ abstract class AbstractVisualObject : VisualObject {
@Transient
override var parent: VisualGroup? = null
protected abstract var properties: Config?
/**
* Object own properties excluding styles and inheritance
*/
protected abstract var ownProperties: Config?
final override var styles: List<String>
get() = properties?.get(STYLE_KEY).stringList
get() = ownProperties?.get(STYLE_KEY).stringList
set(value) {
setProperty(STYLE_KEY, Value.of(value))
setItem(STYLE_KEY, Value.of(value))
updateStyles(value)
}
@ -40,11 +43,11 @@ abstract class AbstractVisualObject : VisualObject {
/**
* The config is initialized and assigned on-demand.
* To avoid unnecessary allocations, one should access [properties] via [getProperty] instead.
* To avoid unnecessary allocations, one should access [ownProperties] via [getProperty] instead.
*/
override val config: Config
get() = properties ?: Config().also { config ->
properties = config.apply { onChange(this, ::propertyChanged) }
get() = ownProperties ?: Config().also { config ->
ownProperties = config.apply { onChange(this, ::propertyChanged) }
}
@Transient
@ -79,18 +82,18 @@ abstract class AbstractVisualObject : VisualObject {
/**
* All available properties in a layered form
*/
override fun allProperties(): Laminate = Laminate(properties, mergedStyles, parent?.allProperties())
override fun properties(): Laminate = Laminate(ownProperties, mergedStyles, parent?.properties())
override fun getProperty(name: Name, inherit: Boolean): MetaItem<*>? {
return if (inherit) {
sequence {
yield(properties?.get(name))
yield(ownProperties?.get(name))
yield(mergedStyles[name])
yield(parent?.getProperty(name, inherit))
}.merge()
} else {
sequence {
yield(properties?.get(name))
yield(ownProperties?.get(name))
yield(mergedStyles[name])
}.merge()
}
@ -100,8 +103,8 @@ abstract class AbstractVisualObject : VisualObject {
* Reset all properties to their default values
*/
fun resetProperties() {
properties?.removeListener(this)
properties = null
ownProperties?.removeListener(this)
ownProperties = null
}
companion object {

@ -13,7 +13,7 @@ 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
override var ownProperties: Config? = null
@SerialName("children")
private val _children = HashMap<NameToken, VisualObject>()

@ -38,12 +38,18 @@ class StyleSheet private constructor(private val styleMap: MutableMap<String, Me
}
}
/**
* Set or clear the style
*/
operator fun set(key: String, style: Meta?) {
val oldStyle = styleMap[key]
define(key, style)
owner?.styleChanged(key, oldStyle, style)
}
/**
* Create and set a style
*/
operator fun set(key: String, builder: MetaBuilder.() -> Unit) {
val newStyle = get(key)?.edit(builder) ?: Meta(builder)
set(key, newStyle.seal())
@ -75,6 +81,8 @@ private fun VisualObject.styleChanged(key: String, oldStyle: Meta?, newStyle: Me
tokens.forEach { parent?.propertyChanged(it, oldStyle?.get(it), newStyle?.get(it)) }
}
if (this is VisualGroup) {
this.forEach { it.styleChanged(key, oldStyle, newStyle) }
for (obj in this) {
obj.styleChanged(key, oldStyle, newStyle)
}
}
}

@ -6,8 +6,7 @@ import hep.dataforge.provider.Provider
/**
* Represents a group of [VisualObject] instances
*/
interface VisualGroup : Provider, Iterable<VisualObject>,
VisualObject {
interface VisualGroup : Provider, VisualObject {
/**
* A map of top level named children
*/
@ -15,6 +14,10 @@ interface VisualGroup : Provider, Iterable<VisualObject>,
override val defaultTarget: String get() = VisualObject.TYPE
/**
* A stylesheet for this group and its descendants. Stylesheet is not applied directly,
* but instead is just a repository for named configutations
*/
val styleSheet: StyleSheet?
/**
@ -35,12 +38,6 @@ interface VisualGroup : Provider, Iterable<VisualObject>,
else -> emptyMap()
}
/**
* Iterate over children of this group
*/
override fun iterator(): Iterator<VisualObject> = children.values.iterator()
operator fun get(name: Name): VisualObject? {
return when {
name.isEmpty() -> this
@ -65,7 +62,10 @@ interface VisualGroup : Provider, Iterable<VisualObject>,
}
}
data class StyleRef(val group: VisualGroup, val styleName: Name)
/**
* Iterate over children of this group
*/
operator fun VisualGroup.iterator(): Iterator<VisualObject> = children.values.iterator()
val VisualGroup.isEmpty: Boolean get() = this.children.isEmpty()

@ -12,9 +12,6 @@ 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)
//private fun Laminate.withBottom(meta: Meta): Laminate = Laminate(layers + meta)
/**
* A root type for display hierarchy
*/
@ -28,16 +25,19 @@ interface VisualObject : Configurable {
var parent: VisualGroup?
/**
* All properties including styles and prototypes if present, but without inheritance
* All properties including styles and prototypes if present, including inherited ones
*/
fun allProperties(): Laminate
fun properties(): Laminate
/**
* Get property including or excluding parent properties
*/
fun getProperty(name: Name, inherit: Boolean): MetaItem<*>?
override fun getProperty(name: Name): MetaItem<*>? = getProperty(name, true)
/**
* Ger a property including inherited values
*/
override fun getItem(name: Name): MetaItem<*>? = getProperty(name, true)
/**
* Trigger property invalidation event. If [name] is empty, notify that the whole object is changed
@ -71,17 +71,14 @@ interface VisualObject : Configurable {
private val VISUAL_OBJECT_SERIALIZER = PolymorphicSerializer(VisualObject::class)
fun serializer() = VISUAL_OBJECT_SERIALIZER
//const val META_KEY = "@meta"
//const val TAGS_KEY = "@tags"
}
}
/**
* Get [VisualObject] property using key as a String
*/
fun VisualObject.getProperty(key: String, inherit: Boolean = true): MetaItem<*>? = getProperty(key.toName(), inherit)
fun VisualObject.getProperty(key: String, inherit: Boolean = true): MetaItem<*>? =
getProperty(key.toName(), inherit)
/**
* Add style name to the list of styles to be resolved later. The style with given name does not necessary exist at the moment.
@ -90,35 +87,7 @@ fun VisualObject.useStyle(name: String) {
styles = styles + name
}
//private tailrec fun VisualObject.topGroup(): VisualGroup? {
// val parent = this.parent
// return if (parent == null) {
// this as? VisualGroup
// }
// else {
// parent.topGroup()
// }
//}
//
///**
// * Add or update given style on a top-most reachable parent group and apply it to this object
// */
//fun VisualObject.useStyle(name: String, builder: MetaBuilder.() -> Unit) {
// val styleName = name.toName()
// topGroup()?.updateStyle(styleName, builder) ?: error("Can't find parent group for $this")
// useStyle(styleName)
//}
tailrec fun VisualObject.findStyle(name: String): Meta? =
(this as? VisualGroup)?.styleSheet?.get(name) ?: parent?.findStyle(name)
fun VisualObject.findAllStyles(): Laminate = Laminate(styles.mapNotNull(::findStyle))
//operator fun VisualObject.get(name: Name): VisualObject?{
// return when {
// name.isEmpty() -> this
// this is VisualGroup -> this[name]
// else -> null
// }
//}

@ -1,131 +0,0 @@
package hep.dataforge.vis
import hep.dataforge.meta.*
import hep.dataforge.names.Name
import hep.dataforge.names.asName
import hep.dataforge.values.Value
import kotlin.jvm.JvmName
import kotlin.properties.ReadOnlyProperty
import kotlin.properties.ReadWriteProperty
import kotlin.reflect.KProperty
/**
* A delegate for display object properties
*/
class VisualObjectDelegate(
val key: Name?,
val default: MetaItem<*>?,
val inherited: Boolean
) : ReadWriteProperty<VisualObject, MetaItem<*>?> {
override fun getValue(thisRef: VisualObject, property: KProperty<*>): MetaItem<*>? {
val name = key ?: property.name.asName()
return if (inherited) {
thisRef.getProperty(name)
} else {
thisRef.config[name]
} ?: default
}
override fun setValue(thisRef: VisualObject, property: KProperty<*>, value: MetaItem<*>?) {
val name = key ?: property.name.asName()
thisRef.config[name] = value
}
}
class VisualObjectDelegateWrapper<T>(
val obj: VisualObject,
val key: Name?,
val default: T,
val inherited: Boolean,
val write: Config.(name: Name, value: T) -> Unit = { name, value -> set(name, value) },
val read: (MetaItem<*>?) -> T?
) : ReadWriteProperty<Any?, T> {
//private var cachedName: Name? = null
override fun getValue(thisRef: Any?, property: KProperty<*>): T {
val name = key ?: property.name.asName()
return read(obj.getProperty(name, inherited)) ?: default
}
override fun setValue(thisRef: Any?, property: KProperty<*>, value: T) {
val name = key ?: property.name.asName()
obj.config[name] = value
}
}
fun VisualObject.value(default: Value? = null, name: Name? = null, inherited: Boolean = false) =
VisualObjectDelegateWrapper(this, name, default, inherited) { it.value }
fun VisualObject.string(default: String? = null, name: Name? = null, inherited: Boolean = false) =
VisualObjectDelegateWrapper(this, name, default, inherited) { it.string }
fun VisualObject.boolean(default: Boolean? = null, name: Name? = null, inherited: Boolean = false) =
VisualObjectDelegateWrapper(this, name, default, inherited) { it.boolean }
fun VisualObject.number(default: Number? = null, name: Name? = null, inherited: Boolean = false) =
VisualObjectDelegateWrapper(this, name, default, inherited) { it.number }
fun VisualObject.double(default: Double? = null, name: Name? = null, inherited: Boolean = false) =
VisualObjectDelegateWrapper(this, name, default, inherited) { it.double }
fun VisualObject.int(default: Int? = null, name: Name? = null, inherited: Boolean = false) =
VisualObjectDelegateWrapper(this, name, default, inherited) { it.int }
fun VisualObject.node(name: Name? = null, inherited: Boolean = true) =
VisualObjectDelegateWrapper(this, name, null, inherited) { it.node }
fun VisualObject.item(name: Name? = null, inherited: Boolean = true) =
VisualObjectDelegateWrapper(this, name, null, inherited) { it }
//fun <T : Configurable> Configurable.spec(spec: Specification<T>, key: String? = null) = ChildConfigDelegate<T>(key) { spec.wrap(this) }
@JvmName("safeString")
fun VisualObject.string(default: String, name: Name? = null, inherited: Boolean = false) =
VisualObjectDelegateWrapper(this, name, default, inherited) { it.string }
@JvmName("safeBoolean")
fun VisualObject.boolean(default: Boolean, name: Name? = null, inherited: Boolean = false) =
VisualObjectDelegateWrapper(this, name, default, inherited) { it.boolean }
@JvmName("safeNumber")
fun VisualObject.number(default: Number, name: Name? = null, inherited: Boolean = false) =
VisualObjectDelegateWrapper(this, name, default, inherited) { it.number }
@JvmName("safeDouble")
fun VisualObject.double(default: Double, name: Name? = null, inherited: Boolean = false) =
VisualObjectDelegateWrapper(this, name, default, inherited) { it.double }
@JvmName("safeInt")
fun VisualObject.int(default: Int, name: Name? = null, inherited: Boolean = false) =
VisualObjectDelegateWrapper(this, name, default, inherited) { it.int }
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) }
}
//merge properties
fun <T> VisualObject.merge(
name: Name? = null,
transformer: (Sequence<MetaItem<*>>) -> T
): ReadOnlyProperty<VisualObject, T> {
return object : ReadOnlyProperty<Any?, T> {
override fun getValue(thisRef: Any?, property: KProperty<*>): T {
val actualName = name ?: property.name.asName()
val sequence = sequence<MetaItem<*>> {
var thisObj: VisualObject? = this@merge
while (thisObj != null) {
thisObj.config[actualName]?.let { yield(it) }
thisObj = thisObj.parent
}
}
return transformer(sequence)
}
}
}

@ -5,25 +5,9 @@ import hep.dataforge.meta.MetaItem
import hep.dataforge.meta.descriptors.NodeDescriptor
import hep.dataforge.meta.node
import hep.dataforge.names.Name
import hep.dataforge.names.isEmpty
import hep.dataforge.values.ValueType
import hep.dataforge.values.asValue
/**
* Return nearest selectable parent [Name]
*/
tailrec fun Name.selectable(): Name? = when {
isEmpty() -> {
null
}
last()?.body?.startsWith("@") != true -> {
this
}
else -> {
cutLast().selectable()
}
}
fun Sequence<MetaItem<*>?>.merge(): MetaItem<*>? {
return when (val first = filterNotNull().firstOrNull()) {
null -> null

@ -40,7 +40,7 @@ interface Application {
fun startApplication(builder: () -> Application) {
fun start(state: dynamic): Application? {
return if (document.body?.hasClass("testApp") == true) {
return if (document.body?.hasClass("application") == true) {
val application = builder()
@Suppress("UnsafeCastFromDynamic")

@ -1,8 +1,10 @@
package hep.dataforge.js
import hep.dataforge.meta.DFExperimental
import hep.dataforge.properties.Property
import org.w3c.dom.HTMLInputElement
@DFExperimental
fun HTMLInputElement.bindValue(property: Property<String>) {
if (this.onchange != null) error("Input element already bound")
this.onchange = {
@ -16,6 +18,7 @@ fun HTMLInputElement.bindValue(property: Property<String>) {
}
}
@DFExperimental
fun HTMLInputElement.bindChecked(property: Property<Boolean>) {
if (this.onchange != null) error("Input element already bound")
this.onchange = {

@ -36,7 +36,7 @@ class VisualObjectEditorFragment(val selector: (VisualObject) -> Meta) : Fragmen
val config = Config().apply {
update(meta)
onChange(this@VisualObjectEditorFragment) { key, _, after ->
visualObject.setProperty(key, after)
visualObject.setItem(key, after)
}
}
//remember old config reference to cleanup listeners

@ -35,7 +35,7 @@ fun main() {
}
fun start(state: dynamic): ApplicationBase? {
return if (document.body?.hasClass("testApp") == true) {
return if (document.body?.hasClass("application") == true) {
val application = JSRootDemoApp()
@Suppress("UnsafeCastFromDynamic")

@ -8,7 +8,7 @@
integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
<script type="text/javascript" src="dataforge-vis-spatial-gdml-0.1.0-dev.js"></script>
</head>
<body class="testApp">
<body class="application">
<div class="container" id="drop_zone" data-toggle="tooltip" data-placement="right"
title="Для загрузки данных в текстовом формате, надо перетащить файл сюда">
Загрузить данные

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

@ -1,9 +1,9 @@
package hep.dataforge.vis.spatial.gdml
import scientifik.gdml.AUnit
import scientifik.gdml.GDMLPosition
import scientifik.gdml.GDMLRotation
import scientifik.gdml.GDMLSolid
import kotlin.math.PI
enum class LUnit(val value: Float) {
MM(1f),
@ -11,13 +11,6 @@ enum class LUnit(val value: Float) {
M(1000f)
}
enum class AUnit(val value: Float) {
DEG(PI.toFloat() / 180),
DEGREE(PI.toFloat() / 180),
RAD(1f),
RADIAN(1f)
}
fun GDMLPosition.unit(): LUnit = LUnit.valueOf(unit.toUpperCase())
fun GDMLPosition.x(unit: LUnit): Float = if (unit.name == this.unit) {

@ -148,6 +148,7 @@ private fun VisualGroup3D.addSolid(
}
}
}
else -> error("Renderer for $solid not supported yet")
}.apply(block)
}

@ -25,7 +25,7 @@ class Box(
override var rotation: Point3D? = null
override var scale: Point3D? = null
override var properties: Config? = null
override var ownProperties: Config? = null
//TODO add helper for color configuration
override fun <T : Any> toGeometry(geometryBuilder: GeometryBuilder<T>) {

@ -33,7 +33,7 @@ class Composite(
override var rotation: Point3D? = null
override var scale: Point3D? = null
override var properties: Config? = null
override var ownProperties: Config? = null
override val children: Map<NameToken, VisualObject>
get() = mapOf(NameToken("first") to first, NameToken("second") to second)
@ -48,7 +48,7 @@ inline fun MutableVisualGroup.composite(
builder: VisualGroup3D.() -> Unit
): Composite {
val group = VisualGroup3D().apply(builder)
val children = group.filterIsInstance<VisualObject3D>()
val children = group.children.values.filterIsInstance<VisualObject3D>()
if (children.size != 2) error("Composite requires exactly two children")
return Composite(type, children[0], children[1]).also {
it.config.update(group.config)

@ -25,7 +25,7 @@ class ConeSegment(
var angle: Float = PI2
) : AbstractVisualObject(), VisualObject3D, Shape {
override var properties: Config? = null
override var ownProperties: Config? = null
override var position: Point3D? = null
override var rotation: Point3D? = null

@ -14,7 +14,7 @@ import kotlinx.serialization.UseSerializers
@SerialName("3d.convex")
class Convex(val points: List<Point3D>) : AbstractVisualObject(), VisualObject3D {
override var properties: Config? = null
override var ownProperties: Config? = null
override var position: Point3D? = null
override var rotation: Point3D? = null

@ -45,7 +45,7 @@ class Extruded(
var layers: MutableList<Layer> = ArrayList()
) : AbstractVisualObject(), VisualObject3D, Shape {
override var properties: Config? = null
override var ownProperties: Config? = null
override var position: Point3D? = null
override var rotation: Point3D? = null

@ -13,7 +13,7 @@ import kotlinx.serialization.UseSerializers
@Serializable
@SerialName("3d.label")
class Label3D(var text: String, var fontSize: Double, var fontFamily: String) : AbstractVisualObject(), VisualObject3D {
override var properties: Config? = null
override var ownProperties: Config? = null
override var position: Point3D? = null
override var rotation: Point3D? = null

@ -78,17 +78,17 @@ class Material3D : Scheme() {
* Set color as web-color
*/
fun VisualObject3D.color(webColor: String) {
setProperty(MATERIAL_COLOR_KEY, webColor.asValue())
setItem(MATERIAL_COLOR_KEY, webColor.asValue())
}
/**
* Set color as integer
*/
fun VisualObject3D.color(rgb: Int) {
setProperty(MATERIAL_COLOR_KEY, rgb.asValue())
setItem(MATERIAL_COLOR_KEY, rgb.asValue())
}
fun VisualObject3D.color(r: UByte, g: UByte, b: UByte) = setProperty(
fun VisualObject3D.color(r: UByte, g: UByte, b: UByte) = setItem(
MATERIAL_COLOR_KEY,
Colors.rgbToMeta(r, g, b)
)
@ -97,13 +97,13 @@ fun VisualObject3D.color(r: UByte, g: UByte, b: UByte) = setProperty(
* Web colors representation of the color in `#rrggbb` format or HTML name
*/
var VisualObject3D.color: String?
get() = getProperty(MATERIAL_COLOR_KEY)?.let { Colors.fromMeta(it) }
get() = getItem(MATERIAL_COLOR_KEY)?.let { Colors.fromMeta(it) }
set(value) {
setProperty(MATERIAL_COLOR_KEY, value?.asValue())
setItem(MATERIAL_COLOR_KEY, value?.asValue())
}
val VisualObject3D.material: Material3D?
get() = getProperty(MATERIAL_KEY).node?.let { Material3D.wrap(it) }
get() = getItem(MATERIAL_KEY).node?.let { Material3D.wrap(it) }
fun VisualObject3D.material(builder: Material3D.() -> Unit) {
val node = config[MATERIAL_KEY].node
@ -115,7 +115,7 @@ fun VisualObject3D.material(builder: Material3D.() -> Unit) {
}
var VisualObject3D.opacity: Double?
get() = getProperty(MATERIAL_OPACITY_KEY).double
get() = getItem(MATERIAL_OPACITY_KEY).double
set(value) {
setProperty(MATERIAL_OPACITY_KEY, value?.asValue())
setItem(MATERIAL_OPACITY_KEY, value?.asValue())
}

@ -16,7 +16,7 @@ import kotlinx.serialization.UseSerializers
@Serializable
@SerialName("3d.line")
class PolyLine(var points: List<Point3D>) : AbstractVisualObject(), VisualObject3D {
override var properties: Config? = null
override var ownProperties: Config? = null
override var position: Point3D? = null
override var rotation: Point3D? = null

@ -34,7 +34,7 @@ class Proxy private constructor(
override var rotation: Point3D? = null
override var scale: Point3D? = null
override var properties: Config? = null
override var ownProperties: Config? = null
/**
* Recursively search for defined template in the parent
@ -51,14 +51,14 @@ class Proxy private constructor(
override fun getProperty(name: Name, inherit: Boolean): MetaItem<*>? {
return if (inherit) {
sequence {
yield(properties?.get(name))
yield(ownProperties?.get(name))
yield(mergedStyles[name])
yield(prototype.getProperty(name))
yield(prototype.getItem(name))
yield(parent?.getProperty(name, inherit))
}.merge()
} else {
sequence {
yield(properties?.get(name))
yield(ownProperties?.get(name))
yield(mergedStyles[name])
yield(prototype.getProperty(name, false))
}.merge()
@ -84,8 +84,8 @@ class Proxy private constructor(
?: error("Prototype with name $name not found in $this")
}
override fun allProperties(): Laminate =
Laminate(properties, mergedStyles, prototype.allProperties(), parent?.allProperties())
override fun properties(): Laminate =
Laminate(ownProperties, mergedStyles, prototype.properties(), parent?.properties())
override fun attachChildren() {
//do nothing
@ -110,7 +110,7 @@ class Proxy private constructor(
)
} ?: emptyMap()
override var properties: Config?
override var ownProperties: Config?
get() = propertyCache[name]
set(value) {
if (value == null) {
@ -130,14 +130,14 @@ class Proxy private constructor(
override fun getProperty(name: Name, inherit: Boolean): MetaItem<*>? {
return if (inherit) {
sequence {
yield(properties?.get(name))
yield(ownProperties?.get(name))
yield(mergedStyles[name])
yield(prototype.getProperty(name))
yield(prototype.getItem(name))
yield(parent?.getProperty(name, inherit))
}.merge()
} else {
sequence {
yield(properties?.get(name))
yield(ownProperties?.get(name))
yield(mergedStyles[name])
yield(prototype.getProperty(name, false))
}.merge()
@ -148,8 +148,8 @@ class Proxy private constructor(
//do nothing
}
override fun allProperties(): Laminate =
Laminate(properties, mergedStyles, prototype.allProperties(), parent?.allProperties())
override fun properties(): Laminate =
Laminate(ownProperties, mergedStyles, prototype.properties(), parent?.properties())
override val descriptor: NodeDescriptor?

@ -23,7 +23,7 @@ class Sphere(
var theta: Float = PI.toFloat()
) : AbstractVisualObject(), VisualObject3D, Shape {
override var properties: Config? = null
override var ownProperties: Config? = null
override var position: Point3D? = null
override var rotation: Point3D? = null

@ -29,7 +29,7 @@ class Tube(
override var rotation: Point3D? = null
override var scale: Point3D? = null
override var properties: Config? = null
override var ownProperties: Config? = null
init {
require(radius > 0)

@ -55,7 +55,7 @@ class Visual3D(meta: Meta) : AbstractPlugin(meta) {
}
@OptIn(UnstableDefault::class)
internal val json = Json(
val json = Json(
JsonConfiguration(
prettyPrint = true,
useArrayPolymorphism = false,

@ -46,7 +46,7 @@ class VisualGroup3D : AbstractVisualGroup(), VisualObject3D, PrototypeHolder {
}
//FIXME to be lifted to AbstractVisualGroup after https://github.com/Kotlin/kotlinx.serialization/issues/378 is fixed
override var properties: Config? = null
override var ownProperties: Config? = null
override var position: Point3D? = null
override var rotation: Point3D? = null
@ -121,7 +121,7 @@ internal class Prototypes(
override fun createGroup() = SimpleVisualGroup()
override var properties: Config?
override var ownProperties: Config?
get() = null
set(_) {
error("Can't define properties for prototypes block")

@ -87,9 +87,9 @@ interface VisualObject3D : VisualObject {
* Count number of layers to the top object. Return 1 if this is top layer
*/
var VisualObject3D.layer: Int
get() = getProperty(LAYER_KEY).int ?: 0
get() = getItem(LAYER_KEY).int ?: 0
set(value) {
setProperty(LAYER_KEY, value.asValue())
setItem(LAYER_KEY, value.asValue())
}
fun Renderer<VisualObject3D>.render(meta: Meta = Meta.EMPTY, action: VisualGroup3D.() -> Unit) =
@ -110,8 +110,8 @@ enum class RotationOrder {
* Rotation order
*/
var VisualObject3D.rotationOrder: RotationOrder
get() = getProperty(VisualObject3D.ROTATION_ORDER_KEY).enum<RotationOrder>() ?: RotationOrder.XYZ
set(value) = setProperty(VisualObject3D.ROTATION_ORDER_KEY, value.name.asValue())
get() = getItem(VisualObject3D.ROTATION_ORDER_KEY).enum<RotationOrder>() ?: RotationOrder.XYZ
set(value) = setItem(VisualObject3D.ROTATION_ORDER_KEY, value.name.asValue())
/**
@ -119,11 +119,11 @@ var VisualObject3D.rotationOrder: RotationOrder
*/
var VisualObject3D.detail: Int?
get() = getProperty(DETAIL_KEY, false).int
set(value) = setProperty(DETAIL_KEY, value?.asValue())
set(value) = setItem(DETAIL_KEY, value?.asValue())
var VisualObject.visible: Boolean?
get() = getProperty(VISIBLE_KEY).boolean
set(value) = setProperty(VISIBLE_KEY, value?.asValue())
get() = getItem(VISIBLE_KEY).boolean
set(value) = setItem(VISIBLE_KEY, value?.asValue())
/**
* If this property is true, the object will be ignored on render.
@ -131,7 +131,7 @@ var VisualObject.visible: Boolean?
*/
var VisualObject.ignore: Boolean?
get() = getProperty(IGNORE_KEY, false).boolean
set(value) = setProperty(IGNORE_KEY, value?.asValue())
set(value) = setItem(IGNORE_KEY, value?.asValue())
//var VisualObject.selected: Boolean?
// get() = getProperty(SELECTED_KEY).boolean

@ -24,7 +24,7 @@ class ConvexTest {
}
}
val convex = group.first() as Convex
val convex = group.children.values.first() as Convex
val json = Visual3D.json.toJson(Convex.serializer(), convex)
val meta = json.toMetaItem().node!!

@ -44,7 +44,7 @@ class GroupTest {
}
}
assertEquals(3, group.count())
assertEquals(3, group.children.count())
assertEquals(300.0, (group["intersect"] as VisualObject3D).y.toDouble())
assertEquals(-300.0, (group["subtract"] as VisualObject3D).y.toDouble())
}

@ -18,7 +18,7 @@ class PropertyTest {
box = box(100, 100, 100)
}
}
assertEquals(22, box?.getProperty("test".asName()).int)
assertEquals(22, box?.getItem("test".asName()).int)
}
@Test
@ -36,7 +36,7 @@ class PropertyTest {
}
}
}
assertEquals(22, box?.getProperty("test".asName()).int)
assertEquals(22, box?.getItem("test".asName()).int)
}
@Test

@ -85,9 +85,9 @@ fun Mesh.applyEdges(obj: VisualObject3D) {
(it as LineSegments).dispose()
}
//inherited edges definition, enabled by default
if (obj.getProperty(MeshThreeFactory.EDGES_ENABLED_KEY).boolean != false) {
if (obj.getItem(MeshThreeFactory.EDGES_ENABLED_KEY).boolean != false) {
val material = ThreeMaterials.getLineMaterial(obj.getProperty(MeshThreeFactory.EDGES_MATERIAL_KEY).node)
val material = ThreeMaterials.getLineMaterial(obj.getItem(MeshThreeFactory.EDGES_MATERIAL_KEY).node)
add(
LineSegments(
EdgesGeometry(geometry as BufferGeometry),
@ -105,8 +105,8 @@ fun Mesh.applyWireFrame(obj: VisualObject3D) {
(it as LineSegments).dispose()
}
//inherited wireframe definition, disabled by default
if (obj.getProperty(MeshThreeFactory.WIREFRAME_ENABLED_KEY).boolean == true) {
val material = ThreeMaterials.getLineMaterial(obj.getProperty(MeshThreeFactory.WIREFRAME_MATERIAL_KEY).node)
if (obj.getItem(MeshThreeFactory.WIREFRAME_ENABLED_KEY).boolean == true) {
val material = ThreeMaterials.getLineMaterial(obj.getItem(MeshThreeFactory.WIREFRAME_MATERIAL_KEY).node)
add(
LineSegments(
WireframeGeometry(geometry as BufferGeometry),

@ -2,7 +2,7 @@ package hep.dataforge.vis.spatial.three
import hep.dataforge.context.Context
import hep.dataforge.meta.Meta
import hep.dataforge.meta.getProperty
import hep.dataforge.meta.getItem
import hep.dataforge.meta.string
import hep.dataforge.names.Name
import hep.dataforge.names.plus
@ -160,7 +160,7 @@ class ThreeCanvas(element: HTMLElement, val three: ThreePlugin, val canvas: Canv
}
private fun addControls(element: Node, controls: Controls) {
when (controls.getProperty("type").string) {
when (controls.getItem("type").string) {
"trackball" -> TrackballControls(camera, element)
else -> OrbitControls(camera, element)
}

@ -18,7 +18,7 @@ object ThreeLineFactory : ThreeFactory<PolyLine> {
vertices = obj.points.toTypedArray()
}
val material = ThreeMaterials.getLineMaterial(obj.getProperty(MeshThreeFactory.EDGES_MATERIAL_KEY).node)
val material = ThreeMaterials.getLineMaterial(obj.getItem(MeshThreeFactory.EDGES_MATERIAL_KEY).node)
material.linewidth = obj.thickness.toDouble()
material.color = obj.color?.let { Color(it) } ?: DEFAULT_LINE_COLOR

@ -5,7 +5,6 @@ import hep.dataforge.values.ValueType
import hep.dataforge.vis.Colors
import hep.dataforge.vis.VisualObject
import hep.dataforge.vis.spatial.Material3D
import hep.dataforge.vis.spatial.Material3D.Companion.MATERIAL_SPECULAR_COLOR_KEY
import info.laht.threekt.materials.LineBasicMaterial
import info.laht.threekt.materials.Material
import info.laht.threekt.materials.MeshBasicMaterial
@ -45,7 +44,7 @@ object ThreeMaterials {
}
fun getMaterial(visualObject3D: VisualObject): Material {
val meta = visualObject3D.getProperty(Material3D.MATERIAL_KEY).node ?: return ThreeMaterials.DEFAULT
val meta = visualObject3D.getItem(Material3D.MATERIAL_KEY).node ?: return ThreeMaterials.DEFAULT
return if (meta[Material3D.SPECULAR_COLOR_KEY] != null) {
MeshPhongMaterial().apply {
color = meta[Material3D.COLOR_KEY]?.getColor() ?: DEFAULT_COLOR

@ -25,7 +25,7 @@ class CustomThreeVisualObject(val threeFactory: ThreeFactory<VisualObject3D>) :
override var rotation: Point3D? = null
override var scale: Point3D? = null
override var properties: Config? = null
override var ownProperties: Config? = null
override fun toObject3D(): Object3D = threeFactory(this)

@ -73,7 +73,7 @@ class FX3DPlugin : AbstractPlugin() {
is PolyLine -> PolyLine3D(
obj.points.map { it.point },
obj.thickness.toFloat(),
obj.getProperty(Material3D.MATERIAL_COLOR_KEY)?.color()
obj.getItem(Material3D.MATERIAL_COLOR_KEY)?.color()
).apply {
this.meshView.cullFace = CullFace.FRONT
}

@ -34,7 +34,7 @@ class VisualObjectFXBinding(val obj: VisualObject) {
operator fun get(key: Name): ObjectBinding<MetaItem<*>?> {
return bindings.getOrPut(key) {
object : ObjectBinding<MetaItem<*>?>() {
override fun computeValue(): MetaItem<*>? = obj.getProperty(key)
override fun computeValue(): MetaItem<*>? = obj.getItem(key)
}
}
}

@ -12,7 +12,7 @@ fun cubes(): GDML = GDML {
val segment = solids.tube("segment", 20, 5.0) {
rmin = 17
deltaphi = 60
aunit = DEG
aunit = AUnit.DEG.title
}
val worldBox = solids.box("LargeBox", 200, 200, 200)
val smallBox = solids.box("smallBox", 30, 30, 30)
@ -24,7 +24,7 @@ fun cubes(): GDML = GDML {
positionref = center.ref()
rotation {
z = 60 * i
unit = DEG
unit = AUnit.DEG.title
}
}
}

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

@ -143,7 +143,7 @@ val GDMLApp = component<GDMLAppProps> { props ->
else -> (visual as? VisualGroup)?.get(selected)
}
if (selectedObject != null) {
configEditor(selectedObject, default = selectedObject.allProperties(), key = selected)
configEditor(selectedObject, default = selectedObject.properties(), key = selected)
}
}
}

@ -11,7 +11,7 @@
<script type="text/javascript" src ="js/jquery-3.4.1.min.js"></script>
<script type="text/javascript" src ="js/bootstrap.bundle.min.js"></script>
</head>
<body class="testApp">
<body class="application">
<div class="container-fluid" id = "app"> </div>
</body>
</html>

@ -24,7 +24,7 @@ class GDMLView : View() {
}
private val propertyEditor = VisualObjectEditorFragment {
it.allProperties()
it.properties()
}.apply {
descriptorProperty.set(Material3D.descriptor)
itemProperty.bind(treeFragment.selectedProperty)

@ -1,6 +1,6 @@
package hep.dataforge.vis.spatial.gdml.demo
import hep.dataforge.meta.setProperty
import hep.dataforge.meta.setItem
import hep.dataforge.values.asValue
import hep.dataforge.vis.spatial.Material3D
import hep.dataforge.vis.spatial.Visual3D
@ -20,7 +20,7 @@ fun Visual3D.Companion.readFile(file: File): VisualGroup3D = when {
solidConfiguration = { parent, solid ->
if (solid.name == "cave") {
setProperty(Material3D.MATERIAL_WIREFRAME_KEY, true.asValue())
setItem(Material3D.MATERIAL_WIREFRAME_KEY, true.asValue())
}
if (parent.physVolumes.isNotEmpty()) {
useStyle("opaque") {

@ -1,4 +1,3 @@
import kotlinx.atomicfu.plugin.gradle.withKotlinTargets
import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation.Companion.MAIN_COMPILATION_NAME
import scientifik.jsDistDirectory
@ -74,4 +73,15 @@ kotlin {
application {
mainClassName = "ru.mipt.npm.muon.monitor.server.MMServerKt"
}
distributions {
main {
contents {
from("$buildDir/libs") {
rename("${rootProject.name}-jvm", rootProject.name)
into("lib")
}
}
}
}

@ -63,7 +63,7 @@ class Model {
fun reset() {
map.values.forEach {
it.config
it.setProperty(Material3D.MATERIAL_COLOR_KEY, null)
it.setItem(Material3D.MATERIAL_COLOR_KEY, null)
}
tracks.removeAll()
}

@ -155,7 +155,7 @@ val MMApp = component<MMAppProps> { props ->
else -> visual[selected]
}
if (selectedObject != null) {
configEditor(selectedObject, default = selectedObject.allProperties(), key = selected)
configEditor(selectedObject, default = selectedObject.properties(), key = selected)
}
}
}

@ -10,7 +10,7 @@
<script type="text/javascript" src ="js/jquery-3.4.1.min.js"></script>
<script type="text/javascript" src ="js/bootstrap.bundle.min.js"></script>
</head>
<body class="testApp">
<body class="application">
<div class="container-fluid" id = "app"> </div>
</body>
</html>

@ -4,7 +4,7 @@ package hep.dataforge.vis.spatial.demo
import hep.dataforge.meta.int
import hep.dataforge.meta.number
import hep.dataforge.meta.setProperty
import hep.dataforge.meta.setItem
import hep.dataforge.names.plus
import hep.dataforge.names.startsWith
import hep.dataforge.values.asValue
@ -26,13 +26,13 @@ import kotlin.reflect.KClass
internal var VisualObject3D.variableZSize: Number
get() = getProperty(Z_SIZE_KEY, false).number ?: 0f
set(value) {
setProperty(Z_SIZE_KEY, value.asValue())
setItem(Z_SIZE_KEY, value.asValue())
}
internal var VisualObject3D.value: Int
get() = getProperty("value", false).int ?: 0
set(value) {
setProperty("value", value.asValue())
setItem("value", value.asValue())
val size = value.toFloat() / 255f * 20f
scaleZ = size
z = -size / 2

@ -8,7 +8,7 @@
integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
<script type="text/javascript" src="main.bundle.js"></script>
</head>
<body class="testApp">
<body class="application">
<div class="container">
<h1>Demo grid</h1>
</div>

@ -7,7 +7,7 @@
<link rel="stylesheet" href="css/common.css">
<script type="text/javascript" src="playground.js"></script>
</head>
<body class="testApp">
<body class="application">
<div class="container">
<h1>Playground</h1>
</div>

@ -1,4 +1,7 @@
pluginManagement {
val kotlinVersion = "1.3.72"
val toolsVersion = "0.5.2"
repositories {
mavenLocal()
jcenter()
@ -10,11 +13,18 @@ pluginManagement {
maven("https://dl.bintray.com/mipt-npm/dev")
}
plugins {
kotlin("jvm") version kotlinVersion
id("scientifik.mpp") version toolsVersion
id("scientifik.jvm") version toolsVersion
id("scientifik.js") version toolsVersion
id("scientifik.publish") version toolsVersion
}
resolutionStrategy {
eachPlugin {
when (requested.id.id) {
"scientifik.mpp", "scientifik.publish", "scientifik.jvm", "scientifik.js" -> useModule("scientifik:gradle-tools:${requested.version}")
"org.openjfx.javafxplugin" -> useModule("org.openjfx:javafx-plugin:${requested.version}")
"scientifik.mpp", "scientifik.publish", "scientifik.jvm", "scientifik.js" -> useModule("scientifik:gradle-tools:${toolsVersion}")
}
}
}