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

0
CHANGELOG.md Normal file
View File

View 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)

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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 = {

View File

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

View File

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

View File

@ -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="Для загрузки данных в текстовом формате, надо перетащить файл сюда">
Загрузить данные

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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") {

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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