New properties #34

Merged
altavir merged 19 commits from new-properties into dev 2020-12-29 13:35:01 +03:00
33 changed files with 156 additions and 161 deletions
Showing only changes of commit 25a47a9719 - Show all commits

View File

@ -2,8 +2,8 @@ plugins {
id("ru.mipt.npm.project") id("ru.mipt.npm.project")
} }
val dataforgeVersion by extra("0.2.1-dev-5") val dataforgeVersion by extra("0.3.0-dev")
val ktorVersion by extra("1.4.3") val ktorVersion by extra("1.5.0")
val htmlVersion by extra("0.7.2") val htmlVersion by extra("0.7.2")
val kotlinWrappersVersion by extra("pre.129-kotlin-1.4.20") val kotlinWrappersVersion by extra("pre.129-kotlin-1.4.20")
val fxVersion by extra("14") val fxVersion by extra("14")

View File

@ -1,7 +1,6 @@
package hep.dataforge.vision.gdml.demo package hep.dataforge.vision.gdml.demo
import hep.dataforge.meta.DFExperimental import hep.dataforge.meta.DFExperimental
import hep.dataforge.meta.setItem
import hep.dataforge.values.asValue import hep.dataforge.values.asValue
import hep.dataforge.vision.gdml.readFile import hep.dataforge.vision.gdml.readFile
import hep.dataforge.vision.gdml.toVision import hep.dataforge.vision.gdml.toVision

View File

@ -39,15 +39,18 @@ fun Page<Solid>.showcase() {
demo("shapes", "Basic shapes") { demo("shapes", "Basic shapes") {
box(100.0, 100.0, 100.0) { box(100.0, 100.0, 100.0) {
z = -110.0 z = -110.0
color("teal")
} }
sphere(50.0) { sphere(50.0) {
x = 110 x = 110
detail = 16 detail = 16
color("red")
} }
tube(50, height = 10, innerRadius = 25, angle = PI) { tube(50, height = 10, innerRadius = 25, angle = PI) {
y = 110 y = 110
detail = 16 detail = 16
rotationX = PI / 4 rotationX = PI / 4
color("blue")
} }
} }
@ -55,6 +58,7 @@ fun Page<Solid>.showcase() {
val group = group { val group = group {
box(100, 100, 100) { box(100, 100, 100) {
z = 110.0 z = 110.0
opacity = 0.5
} }
box(100, 100, 100) { box(100, 100, 100) {
@ -155,7 +159,7 @@ fun Page<Solid>.showcaseCSG() {
detail = 32 detail = 32
} }
color(Colors.lightgreen) color(Colors.lightgreen)
opacity = 0.3 opacity = 0.5
} }
composite(CompositeType.SUBTRACT) { composite(CompositeType.SUBTRACT) {
y = -300 y = -300
@ -173,9 +177,11 @@ fun Page<Solid>.showcaseCSG() {
demo("CSG.custom", "CSG with manually created object") { demo("CSG.custom", "CSG with manually created object") {
intersect { intersect {
tube(60, 10) { tube(60, 10) {
detail = 64 detail = 32
} }
box(100, 100, 100) box(100, 100, 100)
color("red")
opacity = 0.5
} }
} }
} }

View File

@ -9,7 +9,6 @@ import hep.dataforge.vision.set
import hep.dataforge.vision.setProperty import hep.dataforge.vision.setProperty
import hep.dataforge.vision.solid.* import hep.dataforge.vision.solid.*
import hep.dataforge.vision.solid.Solid.Companion.GEOMETRY_KEY import hep.dataforge.vision.solid.Solid.Companion.GEOMETRY_KEY
import hep.dataforge.vision.solid.SolidMaterial.Companion.MATERIAL_COLOR_KEY
import hep.dataforge.vision.solid.three.* import hep.dataforge.vision.solid.three.*
import info.laht.threekt.core.BufferGeometry import info.laht.threekt.core.BufferGeometry
import info.laht.threekt.core.Object3D import info.laht.threekt.core.Object3D
@ -30,8 +29,6 @@ internal class VariableBox(xSize: Number, ySize: Number, zSize: Number) : ThreeV
scaleX = xSize scaleX = xSize
scaleY = ySize scaleY = ySize
scaleZ = zSize scaleZ = zSize
// getProperty(MeshThreeFactory.EDGES_ENABLED_KEY, inherit = false, includeStyles = false)
// getProperty(MeshThreeFactory.WIREFRAME_ENABLED_KEY, inherit = false, includeStyles = false)
} }
override fun render(three: ThreePlugin): Object3D { override fun render(three: ThreePlugin): Object3D {
@ -69,11 +66,8 @@ internal class VariableBox(xSize: Number, ySize: Number, zSize: Number) : ThreeV
mesh.scale.set(newXSize, newYSize, newZSize) mesh.scale.set(newXSize, newYSize, newZSize)
mesh.updateMatrix() mesh.updateMatrix()
} }
//name.startsWith(MeshThreeFactory.WIREFRAME_KEY) -> mesh.applyWireFrame(this@VariableBox)
name.startsWith(MeshThreeFactory.EDGES_KEY) -> mesh.applyEdges(this@VariableBox) name.startsWith(MeshThreeFactory.EDGES_KEY) -> mesh.applyEdges(this@VariableBox)
name.startsWith(MATERIAL_COLOR_KEY) -> { //name.startsWith(MATERIAL_COLOR_KEY) -> mesh.updateMaterialProperty(this, name)
mesh.updateMaterial(this)
}
else -> mesh.updateProperty(this@VariableBox, name) else -> mesh.updateProperty(this@VariableBox, name)
} }
} }

View File

@ -1,7 +1,8 @@
package hep.dataforge.vision.react package hep.dataforge.vision.react
import hep.dataforge.meta.Meta import hep.dataforge.meta.Meta
import hep.dataforge.meta.MetaItem import hep.dataforge.meta.NodeItem
import hep.dataforge.meta.ValueItem
import hep.dataforge.meta.descriptors.ItemDescriptor import hep.dataforge.meta.descriptors.ItemDescriptor
import hep.dataforge.meta.descriptors.NodeDescriptor import hep.dataforge.meta.descriptors.NodeDescriptor
import hep.dataforge.meta.descriptors.defaultItem import hep.dataforge.meta.descriptors.defaultItem
@ -51,7 +52,7 @@ private fun RBuilder.metaViewerItem(props: MetaViewerProps) {
} }
when (actualItem) { when (actualItem) {
is MetaItem.NodeItem -> { is NodeItem -> {
styledDiv { styledDiv {
css { css {
+TreeStyles.treeLeaf +TreeStyles.treeLeaf
@ -108,7 +109,7 @@ private fun RBuilder.metaViewerItem(props: MetaViewerProps) {
} }
} }
} }
is MetaItem.ValueItem -> { is ValueItem -> {
styledDiv { styledDiv {
css { css {
+TreeStyles.treeLeaf +TreeStyles.treeLeaf

View File

@ -9,6 +9,7 @@ import hep.dataforge.names.plus
import hep.dataforge.values.Value import hep.dataforge.values.Value
import hep.dataforge.vision.hidden import hep.dataforge.vision.hidden
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.channels.awaitClose import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
@ -65,12 +66,12 @@ private val PropertyEditorItem: FunctionalComponent<PropertyEditorProps> =
private fun RBuilder.propertyEditorItem(props: PropertyEditorProps) { private fun RBuilder.propertyEditorItem(props: PropertyEditorProps) {
var expanded: Boolean by useState { true } var expanded: Boolean by useState { true }
val itemName by useState { props.name ?: Name.EMPTY } val itemName by useState { props.name ?: Name.EMPTY }
var item: MetaItem<*>? by useState { props.provider.getItem(itemName) } var item: MetaItem? by useState { props.provider.getItem(itemName) }
val descriptorItem: ItemDescriptor? = props.descriptor?.get(itemName) val descriptorItem: ItemDescriptor? = props.descriptor?.get(itemName)
if(descriptorItem?.hidden == true) return //fail fast for hidden property if(descriptorItem?.hidden == true) return //fail fast for hidden property
var actualItem: MetaItem<Meta>? by useState { var actualItem: MetaItem? by useState {
item ?: props.defaultProvider?.getItem(itemName) ?: descriptorItem?.defaultItem() item ?: props.defaultProvider?.getItem(itemName) ?: descriptorItem?.defaultItem()
} }
@ -110,7 +111,7 @@ private fun RBuilder.propertyEditorItem(props: PropertyEditorProps) {
update() update()
} }
if (actualItem is MetaItem.NodeItem) { if (actualItem is NodeItem) {
styledDiv { styledDiv {
css { css {
+TreeStyles.treeLeaf +TreeStyles.treeLeaf
@ -248,6 +249,7 @@ public fun RBuilder.propertyEditor(
} }
} }
@OptIn(ExperimentalCoroutinesApi::class)
private fun Config.flowUpdates(): Flow<Name> = callbackFlow { private fun Config.flowUpdates(): Flow<Name> = callbackFlow {
onChange(this) { name, _, _ -> onChange(this) { name, _, _ ->
launch { launch {

View File

@ -17,7 +17,7 @@ public object TreeStyles : StyleSheet("treeStyles", true) {
/** /**
* Style the caret/arrow * Style the caret/arrow
*/ */
public val treeCaret by css { public val treeCaret: RuleSet by css {
cursor = Cursor.pointer cursor = Cursor.pointer
userSelect = UserSelect.none userSelect = UserSelect.none
/* Create the caret/arrow with a unicode, and style it */ /* Create the caret/arrow with a unicode, and style it */
@ -32,7 +32,7 @@ public object TreeStyles : StyleSheet("treeStyles", true) {
/** /**
* Rotate the caret/arrow icon when clicked on (using JavaScript) * Rotate the caret/arrow icon when clicked on (using JavaScript)
*/ */
val treeCaredDown by css { public val treeCaredDown:RuleSet by css {
before { before {
content = "\u25B6".quoted content = "\u25B6".quoted
color = Color.black color = Color.black
@ -42,7 +42,7 @@ public object TreeStyles : StyleSheet("treeStyles", true) {
} }
} }
val treeItem by css { public val treeItem:RuleSet by css {
alignItems = Align.center alignItems = Align.center
paddingLeft = 10.px paddingLeft = 10.px
borderLeftStyle = BorderStyle.dashed borderLeftStyle = BorderStyle.dashed
@ -53,27 +53,27 @@ public object TreeStyles : StyleSheet("treeStyles", true) {
borderBottomColor = Color.lightGray borderBottomColor = Color.lightGray
} }
val treeLeaf by css { public val treeLeaf:RuleSet by css {
display = Display.flex display = Display.flex
flexDirection = FlexDirection.row flexDirection = FlexDirection.row
flexWrap = FlexWrap.nowrap flexWrap = FlexWrap.nowrap
//alignItems = Align.center //alignItems = Align.center
} }
val treeLabel by css { public val treeLabel:RuleSet by css {
overflow = Overflow.hidden overflow = Overflow.hidden
flex(flexGrow = 1.0, flexShrink = 1.0) flex(flexGrow = 1.0, flexShrink = 1.0)
} }
val treeLabelInactive by css { public val treeLabelInactive: RuleSet by css {
color = Color.lightGray color = Color.lightGray
} }
val treeLabelSelected by css { public val treeLabelSelected:RuleSet by css {
backgroundColor = Color.lightBlue backgroundColor = Color.lightBlue
} }
val linkButton by css { public val linkButton:RuleSet by css {
backgroundColor = Color.white backgroundColor = Color.white
border = "none" border = "none"
padding(left = 4.pt, right = 4.pt, top = 0.pt, bottom = 0.pt) padding(left = 4.pt, right = 4.pt, top = 0.pt, bottom = 0.pt)
@ -86,7 +86,7 @@ public object TreeStyles : StyleSheet("treeStyles", true) {
} }
} }
val removeButton by css { public val removeButton:RuleSet by css {
backgroundColor = Color.white backgroundColor = Color.white
borderStyle = BorderStyle.solid borderStyle = BorderStyle.solid
borderRadius = 2.px borderRadius = 2.px
@ -104,7 +104,7 @@ public object TreeStyles : StyleSheet("treeStyles", true) {
} }
} }
val resizeableInput by css { public val resizeableInput: RuleSet by css {
overflow = Overflow.hidden overflow = Overflow.hidden
maxWidth = 120.pt maxWidth = 120.pt
flex(flexGrow = 2.0, flexShrink = 2.0, flexBasis = 60.pt) flex(flexGrow = 2.0, flexShrink = 2.0, flexBasis = 60.pt)

View File

@ -20,7 +20,7 @@ import styled.styledInput
import styled.styledSelect import styled.styledSelect
public external interface ValueChooserProps : RProps { public external interface ValueChooserProps : RProps {
var item: MetaItem<*>? var item: MetaItem?
var descriptor: ValueDescriptor? var descriptor: ValueDescriptor?
var valueChanged: ((Value?) -> Unit)? var valueChanged: ((Value?) -> Unit)?
} }
@ -140,7 +140,7 @@ class ValueChooserComponent(props: ValueChooserProps) : RComponent<ValueChooserP
internal fun RBuilder.valueChooser( internal fun RBuilder.valueChooser(
name: Name, name: Name,
item: MetaItem<*>?, item: MetaItem?,
descriptor: ValueDescriptor? = null, descriptor: ValueDescriptor? = null,
callback: (Value?) -> Unit callback: (Value?) -> Unit
) { ) {

View File

@ -1,8 +1,6 @@
package hep.dataforge.vision package hep.dataforge.vision
import hep.dataforge.meta.MetaItem import hep.dataforge.meta.*
import hep.dataforge.meta.get
import hep.dataforge.meta.number
import hep.dataforge.values.ValueType import hep.dataforge.values.ValueType
import hep.dataforge.values.int import hep.dataforge.values.int
import hep.dataforge.values.string import hep.dataforge.values.string
@ -192,9 +190,9 @@ public object Colors {
/** /**
* Convert color represented as Meta to string of format #rrggbb * Convert color represented as Meta to string of format #rrggbb
*/ */
fun fromMeta(item: MetaItem<*>): String { fun fromMeta(item: MetaItem): String {
return when (item) { return when (item) {
is MetaItem.NodeItem<*> -> { is NodeItem -> {
val node = item.node val node = item.node
rgbToString( rgbToString(
node[RED_KEY].number?.toByte()?.toUByte() ?: 0u, node[RED_KEY].number?.toByte()?.toUByte() ?: 0u,
@ -202,7 +200,7 @@ public object Colors {
node[BLUE_KEY].number?.toByte()?.toUByte() ?: 0u node[BLUE_KEY].number?.toByte()?.toUByte() ?: 0u
) )
} }
is MetaItem.ValueItem -> { is ValueItem -> {
if (item.value.type == ValueType.NUMBER) { if (item.value.type == ValueType.NUMBER) {
rgbToString(item.value.int) rgbToString(item.value.int)
} else { } else {

View File

@ -40,7 +40,7 @@ public inline class StyleSheet(private val owner: VisionGroup) {
* Create and set a style * Create and set a style
*/ */
public operator fun set(key: String, builder: MetaBuilder.() -> Unit) { public operator fun set(key: String, builder: MetaBuilder.() -> Unit) {
val newStyle = get(key)?.edit(builder) ?: Meta(builder) val newStyle = get(key)?.builder()?.apply(builder) ?: Meta(builder)
set(key, newStyle.seal()) set(key, newStyle.seal())
} }
@ -99,7 +99,7 @@ public tailrec fun Vision.getStyle(name: String): Meta? =
/** /**
* Resolve an item in all style layers * Resolve an item in all style layers
*/ */
public fun Vision.getStyleItems(name: Name): Sequence<MetaItem<*>> { public fun Vision.getStyleItems(name: Name): Sequence<MetaItem> {
return styles.asSequence().map { return styles.asSequence().map {
getStyle(it) getStyle(it)
}.map { }.map {

View File

@ -1,5 +1,6 @@
package hep.dataforge.vision package hep.dataforge.vision
import hep.dataforge.meta.Meta
import hep.dataforge.meta.MetaItem import hep.dataforge.meta.MetaItem
import hep.dataforge.meta.MutableItemProvider import hep.dataforge.meta.MutableItemProvider
import hep.dataforge.meta.descriptors.Described import hep.dataforge.meta.descriptors.Described
@ -28,6 +29,12 @@ public interface Vision : Described {
@Transient @Transient
public var parent: VisionGroup? public var parent: VisionGroup?
/**
* Properties belonging to this [Vision] potentially including artificial properties
*/
@Transient
public val meta: Meta
/** /**
* A coroutine scope for asynchronous calls and locks * A coroutine scope for asynchronous calls and locks
*/ */
@ -37,7 +44,7 @@ public interface Vision : Described {
* A fast accessor method to get own property (no inheritance or styles). * A fast accessor method to get own property (no inheritance or styles).
* Should be equivalent to `getProperty(name,false,false,false)`. * Should be equivalent to `getProperty(name,false,false,false)`.
*/ */
public fun getOwnProperty(name: Name): MetaItem<*>? public fun getOwnProperty(name: Name): MetaItem?
/** /**
* Get property. * Get property.
@ -49,13 +56,13 @@ public interface Vision : Described {
inherit: Boolean = false, inherit: Boolean = false,
includeStyles: Boolean = true, includeStyles: Boolean = true,
includeDefaults: Boolean = true, includeDefaults: Boolean = true,
): MetaItem<*>? ): MetaItem?
/** /**
* Set the property value * Set the property value
*/ */
public fun setProperty(name: Name, item: MetaItem<*>?, notify: Boolean = true) public fun setProperty(name: Name, item: MetaItem?, notify: Boolean = true)
/** /**
* Subscribe on property updates. The subscription is bound to the given [scope] and canceled when the scope is canceled * Subscribe on property updates. The subscription is bound to the given [scope] and canceled when the scope is canceled
@ -109,8 +116,8 @@ public fun Vision.asyncNotifyPropertyChange(propertyName: Name) {
*/ */
public val Vision.ownProperties: MutableItemProvider public val Vision.ownProperties: MutableItemProvider
get() = object : MutableItemProvider { get() = object : MutableItemProvider {
override fun getItem(name: Name): MetaItem<*>? = getOwnProperty(name) override fun getItem(name: Name): MetaItem? = getOwnProperty(name)
override fun setItem(name: Name, item: MetaItem<*>?): Unit = setProperty(name, item) override fun setItem(name: Name, item: MetaItem?): Unit = setProperty(name, item)
} }
@ -123,14 +130,14 @@ public fun Vision.allProperties(
includeStyles: Boolean? = null, includeStyles: Boolean? = null,
includeDefaults: Boolean = true, includeDefaults: Boolean = true,
): MutableItemProvider = object : MutableItemProvider { ): MutableItemProvider = object : MutableItemProvider {
override fun getItem(name: Name): MetaItem<*>? = getProperty( override fun getItem(name: Name): MetaItem? = getProperty(
name, name,
inherit = inherit ?: (descriptor?.get(name)?.inherited != false), inherit = inherit ?: (descriptor?.get(name)?.inherited != false),
includeStyles = includeStyles ?: (descriptor?.get(name)?.usesStyles == true), includeStyles = includeStyles ?: (descriptor?.get(name)?.usesStyles == true),
includeDefaults = includeDefaults includeDefaults = includeDefaults
) )
override fun setItem(name: Name, item: MetaItem<*>?): Unit = setProperty(name, item) override fun setItem(name: Name, item: MetaItem?): Unit = setProperty(name, item)
} }
/** /**
@ -141,7 +148,7 @@ public fun Vision.getProperty(
inherit: Boolean = false, inherit: Boolean = false,
includeStyles: Boolean = true, includeStyles: Boolean = true,
includeDefaults: Boolean = true, includeDefaults: Boolean = true,
): MetaItem<*>? = getProperty(key.toName(), inherit, includeStyles, includeDefaults) ): MetaItem? = getProperty(key.toName(), inherit, includeStyles, includeDefaults)
/** /**
* A convenience method to pair [getProperty] * A convenience method to pair [getProperty]

View File

@ -1,9 +1,6 @@
package hep.dataforge.vision package hep.dataforge.vision
import hep.dataforge.meta.Config import hep.dataforge.meta.*
import hep.dataforge.meta.MetaItem
import hep.dataforge.meta.MutableMeta
import hep.dataforge.meta.asMetaItem
import hep.dataforge.meta.descriptors.NodeDescriptor import hep.dataforge.meta.descriptors.NodeDescriptor
import hep.dataforge.meta.descriptors.defaultItem import hep.dataforge.meta.descriptors.defaultItem
import hep.dataforge.meta.descriptors.get import hep.dataforge.meta.descriptors.get
@ -40,14 +37,14 @@ public open class VisionBase : Vision {
/** /**
* Object own properties excluding styles and inheritance * Object own properties excluding styles and inheritance
*/ */
public var properties: Config? = null internal var properties: Config? = null
private set
override val meta: Meta get() = properties ?: Meta.EMPTY
@Synchronized @Synchronized
private fun getOrCreateConfig(): Config { private fun getOrCreateConfig(): Config {
if (properties == null) { if (properties == null) {
val newProperties = Config() val newProperties = Config()
properties = newProperties
newProperties.onChange(this) { name, oldItem, newItem -> newProperties.onChange(this) { name, oldItem, newItem ->
if (oldItem != newItem) { if (oldItem != newItem) {
scope.launch { scope.launch {
@ -55,6 +52,7 @@ public open class VisionBase : Vision {
} }
} }
} }
properties = newProperties
} }
return properties!! return properties!!
} }
@ -62,7 +60,7 @@ public open class VisionBase : Vision {
/** /**
* A fast accessor method to get own property (no inheritance or styles * A fast accessor method to get own property (no inheritance or styles
*/ */
override fun getOwnProperty(name: Name): MetaItem<*>? { override fun getOwnProperty(name: Name): MetaItem? {
return properties?.getItem(name) return properties?.getItem(name)
} }
@ -71,7 +69,7 @@ public open class VisionBase : Vision {
inherit: Boolean, inherit: Boolean,
includeStyles: Boolean, includeStyles: Boolean,
includeDefaults: Boolean, includeDefaults: Boolean,
): MetaItem<*>? = sequence { ): MetaItem? = sequence {
yield(getOwnProperty(name)) yield(getOwnProperty(name))
if (includeStyles) { if (includeStyles) {
yieldAll(getStyleItems(name)) yieldAll(getStyleItems(name))
@ -83,7 +81,7 @@ public open class VisionBase : Vision {
}.merge() }.merge()
@Synchronized @Synchronized
override fun setProperty(name: Name, item: MetaItem<*>?, notify: Boolean) { override fun setProperty(name: Name, item: MetaItem?, notify: Boolean) {
getOrCreateConfig().setItem(name, item) getOrCreateConfig().setItem(name, item)
if (notify) { if (notify) {
scope.launch { scope.launch {
@ -121,23 +119,17 @@ public open class VisionBase : Vision {
propertyInvalidationFlow.emit(propertyName) propertyInvalidationFlow.emit(propertyName)
} }
public fun configure(block: suspend MutableMeta<*>.() -> Unit) {
scope.launch {
getOrCreateConfig().block()
}
}
override fun update(change: VisionChange) { override fun update(change: VisionChange) {
fun updateProperties(at: Name, item: MetaItem<*>) { fun updateProperties(at: Name, item: MetaItem) {
when (item) { when (item) {
is MetaItem.ValueItem -> { is ValueItem -> {
if (item.value == Null) { if (item.value == Null) {
setProperty(at, null) setProperty(at, null)
} else } else
setProperty(at, item) setProperty(at, item)
} }
is MetaItem.NodeItem -> item.node.items.forEach { (token, childItem) -> is NodeItem -> item.node.items.forEach { (token, childItem) ->
updateProperties(at + token, childItem) updateProperties(at + token, childItem)
} }
} }

View File

@ -29,7 +29,7 @@ public class VisionChangeBuilder : VisionContainerBuilder<Vision> {
private fun getOrPutChild(visionName: Name): VisionChangeBuilder = private fun getOrPutChild(visionName: Name): VisionChangeBuilder =
children.getOrPut(visionName) { VisionChangeBuilder() } children.getOrPut(visionName) { VisionChangeBuilder() }
public fun propertyChanged(visionName: Name, propertyName: Name, item: MetaItem<*>?) { public fun propertyChanged(visionName: Name, propertyName: Name, item: MetaItem?) {
if (visionName == Name.EMPTY) { if (visionName == Name.EMPTY) {
//Write property removal as [Null] //Write property removal as [Null]
propertyChange[propertyName] = (item ?: Null.asMetaItem()) propertyChange[propertyName] = (item ?: Null.asMetaItem())

View File

@ -12,7 +12,7 @@ public interface VisionPropertyContainer<out T> {
inherit: Boolean = false, inherit: Boolean = false,
includeStyles: Boolean = true, includeStyles: Boolean = true,
includeDefaults: Boolean = true, includeDefaults: Boolean = true,
): MetaItem<*>? ): MetaItem?
public fun setProperty(name: Name, item: MetaItem<*>?, notify: Boolean = true) public fun setProperty(name: Name, item: MetaItem?, notify: Boolean = true)
} }

View File

@ -6,20 +6,16 @@ import hep.dataforge.values.asValue
@DslMarker @DslMarker
public annotation class VisionBuilder public annotation class VisionBuilder
public fun Sequence<MetaItem<*>?>.merge(): MetaItem<*>? = when (val first = firstOrNull { it != null }) { public fun Sequence<MetaItem?>.merge(): MetaItem? = when (val first = firstOrNull { it != null }) {
null -> null null -> null
is MetaItem.ValueItem -> first //fast search for first entry if it is value is ValueItem -> first //fast search for first entry if it is value
is MetaItem.NodeItem -> { is NodeItem -> {
//merge nodes if first encountered node is meta //merge nodes if first encountered node is meta
val laminate: Laminate = Laminate(mapNotNull { it.node }.toList()) val laminate: Laminate = Laminate(mapNotNull { it.node }.toList())
MetaItem.NodeItem(laminate) NodeItem(laminate)
} }
} }
@DFExperimental
public val Vision.properties: Config?
get() = (this as? VisionBase)?.properties
/** /**
* Control visibility of the element * Control visibility of the element
*/ */
@ -29,4 +25,4 @@ public var Vision.visible: Boolean?
public fun Vision.configure(meta: Meta?): Unit = update(VisionChange(properties = meta)) public fun Vision.configure(meta: Meta?): Unit = update(VisionChange(properties = meta))
public fun Vision.configure(block: MutableMeta<*>.() -> Unit): Unit = configure(Meta(block)) public fun Vision.configure(block: MetaBuilder.() -> Unit): Unit = configure(Meta(block))

View File

@ -3,6 +3,7 @@ package hep.dataforge.vision.html
import hep.dataforge.meta.DFExperimental import hep.dataforge.meta.DFExperimental
import hep.dataforge.meta.set import hep.dataforge.meta.set
import hep.dataforge.vision.VisionBase import hep.dataforge.vision.VisionBase
import hep.dataforge.vision.configure
import kotlinx.html.* import kotlinx.html.*
import kotlinx.html.stream.createHTML import kotlinx.html.stream.createHTML
import kotlin.test.Test import kotlin.test.Test
@ -34,7 +35,7 @@ class HtmlTagTest {
div { div {
h2 { +"Properties" } h2 { +"Properties" }
ul { ul {
(vision as? VisionBase)?.properties?.items?.forEach { (vision as? VisionBase)?.meta?.items?.forEach {
li { li {
a { +it.key.toString() } a { +it.key.toString() }
p { +it.value.toString() } p { +it.value.toString() }

View File

@ -134,11 +134,11 @@ public class VisionClient : AbstractPlugin() {
stringData stringData
) )
if(change.vision!= null){ if (change.vision != null) {
renderVision(element, change.vision, outputMeta) renderVision(element, change.vision, outputMeta)
} }
logger.info { "Got update ${change.toString()} for output with name $name" } logger.debug { "Got update $change for output with name $name" }
visionMap[element]?.update(change) visionMap[element]?.update(change)
?: console.info("Target vision for element $element with name $name not found") ?: console.info("Target vision for element $element with name $name not found")
} else { } else {

View File

@ -18,7 +18,7 @@ import tornadofx.*
/** /**
* A display for meta and descriptor * A display for meta and descriptor
*/ */
sealed class FXMeta<M : MetaNode<M>> : Comparable<FXMeta<*>> { sealed class FXMeta<M : TypedMeta<M>> : Comparable<FXMeta<*>> {
abstract val name: NameToken abstract val name: NameToken
abstract val parent: FXMetaNode<M>? abstract val parent: FXMetaNode<M>?
abstract val descriptionProperty: ObservableStringValue abstract val descriptionProperty: ObservableStringValue
@ -35,7 +35,7 @@ sealed class FXMeta<M : MetaNode<M>> : Comparable<FXMeta<*>> {
} }
companion object { companion object {
fun <M : MetaNode<M>> root( fun <M : TypedMeta<M>> root(
node: M, node: M,
descriptor: NodeDescriptor? = null, descriptor: NodeDescriptor? = null,
rootName: String = "root" rootName: String = "root"
@ -47,7 +47,7 @@ sealed class FXMeta<M : MetaNode<M>> : Comparable<FXMeta<*>> {
} }
} }
class FXMetaNode<M : MetaNode<M>>( class FXMetaNode<M : TypedMeta<M>>(
override val name: NameToken, override val name: NameToken,
override val parent: FXMetaNode<M>?, override val parent: FXMetaNode<M>?,
nodeValue: M? = null, nodeValue: M? = null,
@ -89,7 +89,7 @@ class FXMetaNode<M : MetaNode<M>>(
init { init {
bind(nodeProperty, descriptorProperty) bind(nodeProperty, descriptorProperty)
val listener: (Name, MetaItem<*>?, MetaItem<*>?) -> Unit = { name, _, _ -> val listener: (Name, MetaItem?, MetaItem?) -> Unit = { name, _, _ ->
if (name.length == 1) invalidate() if (name.length == 1) invalidate()
} }
@ -115,7 +115,7 @@ class FXMetaNode<M : MetaNode<M>>(
val actualItem = node?.items?.get(token) val actualItem = node?.items?.get(token)
val actualDescriptor = descriptor?.items?.get(token.body) val actualDescriptor = descriptor?.items?.get(token.body)
if (actualItem is MetaItem.NodeItem || actualDescriptor is NodeDescriptor) { if (actualItem is NodeItem || actualDescriptor is NodeDescriptor) {
FXMetaNode(token, this@FXMetaNode) FXMetaNode(token, this@FXMetaNode)
} else { } else {
FXMetaValue(token, this@FXMetaNode) FXMetaValue(token, this@FXMetaNode)
@ -134,7 +134,7 @@ class FXMetaNode<M : MetaNode<M>>(
} }
} }
public class FXMetaValue<M : MetaNode<M>>( public class FXMetaValue<M : TypedMeta<M>>(
override val name: NameToken, override val name: NameToken,
override val parent: FXMetaNode<M> override val parent: FXMetaNode<M>
) : FXMeta<M>() { ) : FXMeta<M>() {
@ -151,10 +151,10 @@ public class FXMetaValue<M : MetaNode<M>>(
//private val innerValueProperty = SimpleObjectProperty(value) //private val innerValueProperty = SimpleObjectProperty(value)
public val valueProperty = descriptorProperty.objectBinding { descriptor -> public val valueProperty = descriptorProperty.objectBinding { descriptor ->
parent.node[name].value ?: descriptor?.default parent.node?.get(name).value ?: descriptor?.default
} }
override val hasValue: ObservableBooleanValue = parent.nodeProperty.booleanBinding { it[name] != null } override val hasValue: ObservableBooleanValue = parent.nodeProperty.booleanBinding { it?.get(name) != null }
public val value by valueProperty public val value by valueProperty
@ -169,12 +169,12 @@ public fun <M : MutableMeta<M>> FXMetaNode<M>.remove(name: NameToken) {
private fun <M : MutableMeta<M>> M.createEmptyNode(token: NameToken, append: Boolean): M { private fun <M : MutableMeta<M>> M.createEmptyNode(token: NameToken, append: Boolean): M {
return if (append && token.hasIndex()) { return if (append && token.hasIndex()) {
val name = token.asName() val name = token.asName()
val index = (getIndexed(name).keys.mapNotNull { it.toIntOrNull() }.max() ?: -1) + 1 val index = (getIndexed(name).keys.mapNotNull { it?.toIntOrNull() }.maxOrNull() ?: -1) + 1
val newName = name.withIndex(index.toString()) val newName = name.withIndex(index.toString())
set(newName, Meta.EMPTY) set(newName, Meta.EMPTY)
get(newName).node!! get(newName).node!!
} else { } else {
this.setNode(token.asName(), Meta.EMPTY) this.set(token.asName(), Meta.EMPTY)
//FIXME possible concurrency bug //FIXME possible concurrency bug
get(token).node!! get(token).node!!
} }

View File

@ -1,9 +1,6 @@
package hep.dataforge.vision.solid package hep.dataforge.vision.solid
import hep.dataforge.meta.MetaItem import hep.dataforge.meta.*
import hep.dataforge.meta.double
import hep.dataforge.meta.get
import hep.dataforge.meta.int
import hep.dataforge.values.ValueType import hep.dataforge.values.ValueType
import hep.dataforge.values.int import hep.dataforge.values.int
import hep.dataforge.values.string import hep.dataforge.values.string
@ -35,9 +32,9 @@ public object FXMaterials {
* Infer color based on meta item * Infer color based on meta item
* @param opacity default opacity * @param opacity default opacity
*/ */
public fun MetaItem<*>.color(opacity: Double = 1.0): Color { public fun MetaItem.color(opacity: Double = 1.0): Color {
return when (this) { return when (this) {
is MetaItem.ValueItem -> if (this.value.type == ValueType.NUMBER) { is ValueItem -> if (this.value.type == ValueType.NUMBER) {
val int = value.int val int = value.int
val red = int and 0x00ff0000 shr 16 val red = int and 0x00ff0000 shr 16
val green = int and 0x0000ff00 shr 8 val green = int and 0x0000ff00 shr 8
@ -46,7 +43,7 @@ public fun MetaItem<*>.color(opacity: Double = 1.0): Color {
} else { } else {
Color.web(this.value.string) Color.web(this.value.string)
} }
is MetaItem.NodeItem -> { is NodeItem -> {
Color.rgb( Color.rgb(
node[Colors.RED_KEY]?.int ?: 0, node[Colors.RED_KEY]?.int ?: 0,
node[Colors.GREEN_KEY]?.int ?: 0, node[Colors.GREEN_KEY]?.int ?: 0,
@ -60,11 +57,11 @@ public fun MetaItem<*>.color(opacity: Double = 1.0): Color {
/** /**
* Infer FX material based on meta item * Infer FX material based on meta item
*/ */
public fun MetaItem<*>?.material(): Material { public fun MetaItem?.material(): Material {
return when (this) { return when (this) {
null -> FXMaterials.GREY null -> FXMaterials.GREY
is MetaItem.ValueItem -> PhongMaterial(color()) is ValueItem -> PhongMaterial(color())
is MetaItem.NodeItem -> PhongMaterial().apply { is NodeItem -> PhongMaterial().apply {
val opacity = node[SolidMaterial.OPACITY_KEY].double ?: 1.0 val opacity = node[SolidMaterial.OPACITY_KEY].double ?: 1.0
diffuseColor = node[SolidMaterial.COLOR_KEY]?.color(opacity) ?: Color.DARKGREY diffuseColor = node[SolidMaterial.COLOR_KEY]?.color(opacity) ?: Color.DARKGREY
specularColor = node[SolidMaterial.SPECULAR_COLOR_KEY]?.color(opacity) ?: Color.WHITE specularColor = node[SolidMaterial.SPECULAR_COLOR_KEY]?.color(opacity) ?: Color.WHITE

View File

@ -13,7 +13,7 @@ import tornadofx.*
* A caching binding collection for [Vision] properties * A caching binding collection for [Vision] properties
*/ */
class VisualObjectFXBinding(val fx: FX3DPlugin, val obj: Vision) { class VisualObjectFXBinding(val fx: FX3DPlugin, val obj: Vision) {
private val bindings = HashMap<Name, ObjectBinding<MetaItem<*>?>>() private val bindings = HashMap<Name, ObjectBinding<MetaItem?>>()
init { init {
obj.onPropertyChange(fx.context) { name -> obj.onPropertyChange(fx.context) { name ->
@ -31,10 +31,10 @@ class VisualObjectFXBinding(val fx: FX3DPlugin, val obj: Vision) {
} }
} }
operator fun get(key: Name): ObjectBinding<MetaItem<*>?> { operator fun get(key: Name): ObjectBinding<MetaItem?> {
return bindings.getOrPut(key) { return bindings.getOrPut(key) {
object : ObjectBinding<MetaItem<*>?>() { object : ObjectBinding<MetaItem?>() {
override fun computeValue(): MetaItem<*>? = obj.getProperty(key) override fun computeValue(): MetaItem? = obj.getProperty(key)
} }
} }
} }
@ -42,19 +42,19 @@ class VisualObjectFXBinding(val fx: FX3DPlugin, val obj: Vision) {
operator fun get(key: String) = get(key.toName()) operator fun get(key: String) = get(key.toName())
} }
fun ObjectBinding<MetaItem<*>?>.value() = objectBinding { it.value } fun ObjectBinding<MetaItem?>.value() = objectBinding { it.value }
fun ObjectBinding<MetaItem<*>?>.string() = stringBinding { it.string } fun ObjectBinding<MetaItem?>.string() = stringBinding { it.string }
fun ObjectBinding<MetaItem<*>?>.number() = objectBinding { it.number } fun ObjectBinding<MetaItem?>.number() = objectBinding { it.number }
fun ObjectBinding<MetaItem<*>?>.double() = objectBinding { it.double } fun ObjectBinding<MetaItem?>.double() = objectBinding { it.double }
fun ObjectBinding<MetaItem<*>?>.float() = objectBinding { it.float } fun ObjectBinding<MetaItem?>.float() = objectBinding { it.float }
fun ObjectBinding<MetaItem<*>?>.int() = objectBinding { it.int } fun ObjectBinding<MetaItem?>.int() = objectBinding { it.int }
fun ObjectBinding<MetaItem<*>?>.long() = objectBinding { it.long } fun ObjectBinding<MetaItem?>.long() = objectBinding { it.long }
fun ObjectBinding<MetaItem<*>?>.node() = objectBinding { it.node } fun ObjectBinding<MetaItem?>.node() = objectBinding { it.node }
fun ObjectBinding<MetaItem<*>?>.string(default: String) = stringBinding { it.string ?: default } fun ObjectBinding<MetaItem?>.string(default: String) = stringBinding { it.string ?: default }
fun ObjectBinding<MetaItem<*>?>.double(default: Double) = doubleBinding { it.double ?: default } fun ObjectBinding<MetaItem?>.double(default: Double) = doubleBinding { it.double ?: default }
fun ObjectBinding<MetaItem<*>?>.float(default: Float) = floatBinding { it.float ?: default } fun ObjectBinding<MetaItem?>.float(default: Float) = floatBinding { it.float ?: default }
fun ObjectBinding<MetaItem<*>?>.int(default: Int) = integerBinding { it.int ?: default } fun ObjectBinding<MetaItem?>.int(default: Int) = integerBinding { it.int ?: default }
fun ObjectBinding<MetaItem<*>?>.long(default: Long) = longBinding { it.long ?: default } fun ObjectBinding<MetaItem?>.long(default: Long) = longBinding { it.long ?: default }
fun <T> ObjectBinding<MetaItem<*>?>.transform(transform: (MetaItem<*>) -> T) = objectBinding { it?.let(transform) } fun <T> ObjectBinding<MetaItem?>.transform(transform: (MetaItem) -> T) = objectBinding { it?.let(transform) }

View File

@ -1,9 +1,8 @@
package hep.dataforge.vision.gdml package hep.dataforge.vision.gdml
import hep.dataforge.meta.DFExperimental import hep.dataforge.meta.DFExperimental
import hep.dataforge.meta.sequence import hep.dataforge.meta.itemSequence
import hep.dataforge.vision.Vision import hep.dataforge.vision.Vision
import hep.dataforge.vision.properties
import hep.dataforge.vision.solid.* import hep.dataforge.vision.solid.*
public expect class Counter() { public expect class Counter() {
@ -27,7 +26,7 @@ internal fun Vision.updateFrom(other: Vision): Vision {
scaleY = scaleY.toDouble() * other.scaleY.toDouble() scaleY = scaleY.toDouble() * other.scaleY.toDouble()
scaleZ = scaleZ.toDouble() * other.scaleZ.toDouble() scaleZ = scaleZ.toDouble() * other.scaleZ.toDouble()
} }
other.properties?.sequence()?.forEach { (name, item) -> other.meta.itemSequence().forEach { (name, item) ->
if (getProperty(name) == null) { if (getProperty(name) == null) {
setProperty(name, item) setProperty(name, item)
} }

View File

@ -1,6 +1,5 @@
package hep.dataforge.vision.solid package hep.dataforge.vision.solid
import hep.dataforge.meta.Meta
import hep.dataforge.meta.update import hep.dataforge.meta.update
import hep.dataforge.names.NameToken import hep.dataforge.names.NameToken
import hep.dataforge.vision.* import hep.dataforge.vision.*
@ -39,18 +38,20 @@ public inline fun VisionContainerBuilder<Solid>.composite(
val group = SolidGroup().apply(builder) val group = SolidGroup().apply(builder)
val children = group.children.values.filterIsInstance<Solid>() val children = group.children.values.filterIsInstance<Solid>()
if (children.size != 2) error("Composite requires exactly two children") if (children.size != 2) error("Composite requires exactly two children")
return Composite(type, children[0], children[1]).also { return Composite(type, children[0], children[1]).also { composite ->
it.configure { update(group.properties ?: Meta.EMPTY) } composite.configure {
update(group.meta)
}
if (group.position != null) { if (group.position != null) {
it.position = group.position composite.position = group.position
} }
if (group.rotation != null) { if (group.rotation != null) {
it.rotation = group.rotation composite.rotation = group.rotation
} }
if (group.scale != null) { if (group.scale != null) {
it.scale = group.scale composite.scale = group.scale
} }
set(name, it) set(name, composite)
} }
} }

View File

@ -85,7 +85,7 @@ public interface Solid : Vision {
if (first.position != second.position) return false if (first.position != second.position) return false
if (first.rotation != second.rotation) return false if (first.rotation != second.rotation) return false
if (first.scale != second.scale) return false if (first.scale != second.scale) return false
if (first.properties != second.properties) return false if (first.meta != second.meta) return false
return true return true
} }

View File

@ -106,16 +106,16 @@ internal class Prototypes(
} }
} }
override fun getOwnProperty(name: Name): MetaItem<*>? = null override fun getOwnProperty(name: Name): MetaItem? = null
override fun getProperty( override fun getProperty(
name: Name, name: Name,
inherit: Boolean, inherit: Boolean,
includeStyles: Boolean, includeStyles: Boolean,
includeDefaults: Boolean, includeDefaults: Boolean,
): MetaItem<*>? = null ): MetaItem? = null
override fun setProperty(name: Name, item: MetaItem<*>?, notify: Boolean) { override fun setProperty(name: Name, item: MetaItem?, notify: Boolean) {
error("Can't ser property of prototypes container") error("Can't ser property of prototypes container")
} }

View File

@ -19,12 +19,12 @@ public class SolidMaterial : Scheme() {
/** /**
* Primary web-color for the material * Primary web-color for the material
*/ */
public var color: ColorAccessor = ColorAccessor(config, COLOR_KEY) public var color: ColorAccessor = ColorAccessor(items, COLOR_KEY)
/** /**
* Specular color for phong material * Specular color for phong material
*/ */
public var specularColor: ColorAccessor = ColorAccessor(config, SPECULAR_COLOR_KEY) public var specularColor: ColorAccessor = ColorAccessor(items, SPECULAR_COLOR_KEY)
/** /**
* Opacity * Opacity
@ -100,16 +100,17 @@ public val Solid.color: ColorAccessor
public var Solid.material: SolidMaterial? public var Solid.material: SolidMaterial?
get() = getProperty(MATERIAL_KEY, inherit = true).node?.let { SolidMaterial.read(it) } get() = getProperty(MATERIAL_KEY, inherit = true).node?.let { SolidMaterial.read(it) }
set(value) = setProperty(MATERIAL_KEY, value?.config) set(value) = setProperty(MATERIAL_KEY, value?.rootNode)
@VisionBuilder @VisionBuilder
public fun Solid.material(builder: SolidMaterial.() -> Unit) { public fun Solid.material(builder: SolidMaterial.() -> Unit) {
val node = allProperties(inherit = true).getItem(MATERIAL_KEY).node
if (node != null) {
SolidMaterial.update(node, builder)
} else {
setProperty(MATERIAL_KEY, SolidMaterial(builder)) setProperty(MATERIAL_KEY, SolidMaterial(builder))
} // val node = getOwnProperty(MATERIAL_KEY).node
// if (node != null) {
// configure(SolidMaterial(builder).config)
// } else {
// setProperty(MATERIAL_KEY, SolidMaterial(builder))
// }
} }
public var Solid.opacity: Number? public var Solid.opacity: Number?

View File

@ -17,7 +17,7 @@ private fun SolidReference.getRefProperty(
inherit: Boolean, inherit: Boolean,
includeStyles: Boolean, includeStyles: Boolean,
includeDefaults: Boolean, includeDefaults: Boolean,
): MetaItem<*>? { ): MetaItem? {
return sequence { return sequence {
yield(getOwnProperty(name)) yield(getOwnProperty(name))
if (includeStyles) { if (includeStyles) {
@ -59,11 +59,11 @@ public class SolidReferenceGroup(
private fun childPropertyName(childName: Name, propertyName: Name): Name = private fun childPropertyName(childName: Name, propertyName: Name): Name =
childToken(childName) + propertyName childToken(childName) + propertyName
private fun getChildProperty(childName: Name, propertyName: Name): MetaItem<*>? { private fun getChildProperty(childName: Name, propertyName: Name): MetaItem? {
return getOwnProperty(childPropertyName(childName, propertyName)) return getOwnProperty(childPropertyName(childName, propertyName))
} }
private fun setChildProperty(childName: Name, propertyName: Name, item: MetaItem<*>?, notify: Boolean) { private fun setChildProperty(childName: Name, propertyName: Name, item: MetaItem?, notify: Boolean) {
setProperty(childPropertyName(childName, propertyName), item, notify) setProperty(childPropertyName(childName, propertyName), item, notify)
} }
@ -79,7 +79,7 @@ public class SolidReferenceGroup(
inherit: Boolean, inherit: Boolean,
includeStyles: Boolean, includeStyles: Boolean,
includeDefaults: Boolean, includeDefaults: Boolean,
): MetaItem<*>? = getRefProperty(name, inherit, includeStyles, includeDefaults) ): MetaItem? = getRefProperty(name, inherit, includeStyles, includeDefaults)
override val descriptor: NodeDescriptor get() = prototype.descriptor override val descriptor: NodeDescriptor get() = prototype.descriptor
@ -99,9 +99,11 @@ public class SolidReferenceGroup(
ReferenceChild(childName + key.asName()) ReferenceChild(childName + key.asName())
} ?: emptyMap() } ?: emptyMap()
override fun getOwnProperty(name: Name): MetaItem<*>? = getChildProperty(childName, name) override val meta: Meta get() =TODO()// getChildProperty(childName, Name.EMPTY).node ?: Meta.EMPTY
override fun setProperty(name: Name, item: MetaItem<*>?, notify: Boolean) { override fun getOwnProperty(name: Name): MetaItem? = getChildProperty(childName, name)
override fun setProperty(name: Name, item: MetaItem?, notify: Boolean) {
setChildProperty(childName, name, item, notify) setChildProperty(childName, name, item, notify)
} }
@ -110,7 +112,7 @@ public class SolidReferenceGroup(
inherit: Boolean, inherit: Boolean,
includeStyles: Boolean, includeStyles: Boolean,
includeDefaults: Boolean, includeDefaults: Boolean,
): MetaItem<*>? = getRefProperty(name, inherit, includeStyles, includeDefaults) ): MetaItem? = getRefProperty(name, inherit, includeStyles, includeDefaults)
override var parent: VisionGroup? override var parent: VisionGroup?
get() { get() {

View File

@ -3,7 +3,7 @@ package hep.dataforge.vision.solid.specifications
import hep.dataforge.meta.* import hep.dataforge.meta.*
public class Axes : Scheme() { public class Axes : Scheme() {
public var visible: Boolean by boolean(!config.isEmpty()) public var visible: Boolean by boolean(rootNode?.isEmpty() != false)
public var size: Double by double(AXIS_SIZE) public var size: Double by double(AXIS_SIZE)
public var width: Double by double(AXIS_WIDTH) public var width: Double by double(AXIS_WIDTH)

View File

@ -9,7 +9,7 @@ import hep.dataforge.vision.solid.*
internal fun mergeChild(parent: VisionGroup, child: Vision): Vision { internal fun mergeChild(parent: VisionGroup, child: Vision): Vision {
return child.apply { return child.apply {
configure(parent.properties) configure(parent.meta)
//parent.properties?.let { config.update(it) } //parent.properties?.let { config.update(it) }

View File

@ -28,7 +28,7 @@ class ConvexTest {
val json = SolidManager.jsonForSolids.encodeToJsonElement(Convex.serializer(), convex) val json = SolidManager.jsonForSolids.encodeToJsonElement(Convex.serializer(), convex)
val meta = json.toMetaItem().node!! 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 NodeItem<*>).node.point3D() }
assertEquals(8, points.count()) assertEquals(8, points.count())
assertEquals(8, convex.points.size) assertEquals(8, convex.points.size)

View File

@ -4,7 +4,6 @@ import hep.dataforge.names.Name
import hep.dataforge.names.toName import hep.dataforge.names.toName
import hep.dataforge.vision.MutableVisionGroup import hep.dataforge.vision.MutableVisionGroup
import hep.dataforge.vision.get import hep.dataforge.vision.get
import hep.dataforge.vision.properties
import kotlin.test.Test import kotlin.test.Test
import kotlin.test.assertEquals import kotlin.test.assertEquals
@ -33,7 +32,7 @@ class SerializationTest {
val string = SolidManager.encodeToString(cube) val string = SolidManager.encodeToString(cube)
println(string) println(string)
val newCube = SolidManager.decodeFromString(string) val newCube = SolidManager.decodeFromString(string)
assertEquals(cube.properties, newCube.properties) assertEquals(cube.meta, newCube.meta)
} }
@Test @Test
@ -54,7 +53,7 @@ class SerializationTest {
val string = SolidManager.encodeToString(group) val string = SolidManager.encodeToString(group)
println(string) println(string)
val reconstructed = SolidManager.decodeFromString(string) as SolidGroup val reconstructed = SolidManager.decodeFromString(string) as SolidGroup
assertEquals(group["cube"]?.properties, reconstructed["cube"]?.properties) assertEquals(group["cube"]?.meta, reconstructed["cube"]?.meta)
} }
} }

View File

@ -1,6 +1,6 @@
package hep.dataforge.vision.solid.three package hep.dataforge.vision.solid.three
import hep.dataforge.meta.getItem import hep.dataforge.meta.get
import hep.dataforge.meta.string import hep.dataforge.meta.string
import hep.dataforge.names.Name import hep.dataforge.names.Name
import hep.dataforge.names.plus import hep.dataforge.names.plus
@ -177,7 +177,7 @@ public class ThreeCanvas(
} }
private fun addControls(element: Node, controls: Controls) { private fun addControls(element: Node, controls: Controls) {
when (controls.getItem("type").string) { when (controls.get("type").string) {
"trackball" -> TrackballControls(camera, element) "trackball" -> TrackballControls(camera, element)
else -> OrbitControls(camera, element) else -> OrbitControls(camera, element)
} }

View File

@ -109,15 +109,15 @@ public object ThreeMaterials {
/** /**
* Infer color based on meta item * Infer color based on meta item
*/ */
public fun MetaItem<*>.getColor(): Color { public fun MetaItem.getColor(): Color {
return when (this) { return when (this) {
is MetaItem.ValueItem -> if (this.value.type == ValueType.NUMBER) { is ValueItem -> if (this.value.type == ValueType.NUMBER) {
val int = value.int val int = value.int
Color(int) Color(int)
} else { } else {
Color(this.value.string) Color(this.value.string)
} }
is MetaItem.NodeItem -> { is NodeItem -> {
Color( Color(
node[Colors.RED_KEY]?.int ?: 0, node[Colors.RED_KEY]?.int ?: 0,
node[Colors.GREEN_KEY]?.int ?: 0, node[Colors.GREEN_KEY]?.int ?: 0,
@ -160,7 +160,7 @@ public fun Mesh.updateMaterial(vision: Vision) {
} }
public fun Mesh.updateMaterialProperty(vision: Vision, propertyName: Name) { public fun Mesh.updateMaterialProperty(vision: Vision, propertyName: Name) {
if (material.cached) { if (material.cached || propertyName == SolidMaterial.MATERIAL_KEY) {
//generate a new material since cached material should not be changed //generate a new material since cached material should not be changed
updateMaterial(vision) updateMaterial(vision)
} else { } else {

View File

@ -17,7 +17,7 @@ import kotlin.math.PI
public val Solid.euler: Euler get() = Euler(rotationX, rotationY, rotationZ, rotationOrder.name) public val Solid.euler: Euler get() = Euler(rotationX, rotationY, rotationZ, rotationOrder.name)
public val MetaItem<*>.vector: Vector3 get() = Vector3(node["x"].float ?: 0f, node["y"].float ?: 0f, node["z"].float ?: 0f) public val MetaItem.vector: Vector3 get() = Vector3(node["x"].float ?: 0f, node["y"].float ?: 0f, node["z"].float ?: 0f)
public fun Geometry.toBufferGeometry(): BufferGeometry = BufferGeometry().apply { fromGeometry(this@toBufferGeometry) } public fun Geometry.toBufferGeometry(): BufferGeometry = BufferGeometry().apply { fromGeometry(this@toBufferGeometry) }