Refactor Group hierarchy

This commit is contained in:
Alexander Nozik 2020-11-13 09:57:46 +03:00
parent dfac01d352
commit 7e037b57fc
26 changed files with 101 additions and 128 deletions

View File

@ -1,13 +1,14 @@
package hep.dataforge.vision.gdml package hep.dataforge.vision.gdml
import hep.dataforge.meta.setItem
import hep.dataforge.meta.string import hep.dataforge.meta.string
import hep.dataforge.names.toName import hep.dataforge.names.toName
import hep.dataforge.values.asValue import hep.dataforge.values.asValue
import hep.dataforge.vision.gdml.demo.cubes import hep.dataforge.vision.gdml.demo.cubes
import hep.dataforge.vision.setProperty
import hep.dataforge.vision.solid.SolidMaterial import hep.dataforge.vision.solid.SolidMaterial
import kotlin.test.Test import kotlin.test.Test
import kotlin.test.assertEquals import kotlin.test.assertEquals
import kotlin.test.assertTrue
class GDMLVisualTest { class GDMLVisualTest {
val gdml = cubes() val gdml = cubes()
@ -24,7 +25,9 @@ class GDMLVisualTest {
@Test @Test
fun testPrototypeProperty() { fun testPrototypeProperty() {
val visual = gdml.toVision() val visual = gdml.toVision()
visual["composite000.segment_0".toName()]?.setItem(SolidMaterial.MATERIAL_COLOR_KEY, "red".asValue()) val child = visual["composite000.segment_0".toName()]
assertEquals("red", visual["composite000.segment_0".toName()]?.getItem(SolidMaterial.MATERIAL_COLOR_KEY).string) assertTrue { child!= null }
child?.setProperty(SolidMaterial.MATERIAL_COLOR_KEY, "red".asValue())
assertEquals("red", child?.getProperty(SolidMaterial.MATERIAL_COLOR_KEY).string)
} }
} }

View File

@ -1,6 +1,7 @@
package ru.mipt.npm.muon.monitor package ru.mipt.npm.muon.monitor
import hep.dataforge.vision.removeAll import hep.dataforge.vision.removeAll
import hep.dataforge.vision.setProperty
import hep.dataforge.vision.solid.* import hep.dataforge.vision.solid.*
import ru.mipt.npm.muon.monitor.Monitor.CENTRAL_LAYER_Z import ru.mipt.npm.muon.monitor.Monitor.CENTRAL_LAYER_Z
import ru.mipt.npm.muon.monitor.Monitor.LOWER_LAYER_Z import ru.mipt.npm.muon.monitor.Monitor.LOWER_LAYER_Z
@ -63,7 +64,7 @@ class Model {
fun reset() { fun reset() {
map.values.forEach { map.values.forEach {
it.config it.config
it.setItem(SolidMaterial.MATERIAL_COLOR_KEY, null) it.setProperty(SolidMaterial.MATERIAL_COLOR_KEY, null)
} }
tracks.removeAll() tracks.removeAll()
} }

View File

@ -1,6 +1,7 @@
package ru.mipt.npm.muon.monitor package ru.mipt.npm.muon.monitor
import hep.dataforge.context.Context import hep.dataforge.context.Context
import hep.dataforge.meta.invoke
import hep.dataforge.names.Name import hep.dataforge.names.Name
import hep.dataforge.names.NameToken import hep.dataforge.names.NameToken
import hep.dataforge.names.isEmpty import hep.dataforge.names.isEmpty
@ -172,7 +173,12 @@ val MMApp = functionalComponent<MMAppProps>("Muon monitor") { props ->
else -> root[selected] else -> root[selected]
} }
if (selectedObject != null) { if (selectedObject != null) {
configEditor(selectedObject, default = selectedObject.getAllProperties(), key = selected) configEditor(
selectedObject.config,
selectedObject.descriptor,
default = selectedObject.getAllProperties(),
key = selected
)
} }
} }
} }

View File

@ -5,12 +5,12 @@ package hep.dataforge.vision.solid.demo
import hep.dataforge.meta.int import hep.dataforge.meta.int
import hep.dataforge.meta.number import hep.dataforge.meta.number
import hep.dataforge.meta.set import hep.dataforge.meta.set
import hep.dataforge.meta.setItem
import hep.dataforge.names.plus import hep.dataforge.names.plus
import hep.dataforge.names.startsWith import hep.dataforge.names.startsWith
import hep.dataforge.values.asValue import hep.dataforge.values.asValue
import hep.dataforge.vision.getProperty import hep.dataforge.vision.getProperty
import hep.dataforge.vision.set import hep.dataforge.vision.set
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.three.* import hep.dataforge.vision.solid.three.*
@ -84,13 +84,13 @@ internal class VariableBox(xSize: Number, ySize: Number, zSize: Number) : ThreeV
var variableZSize: Number var variableZSize: Number
get() = getProperty(Z_SIZE_KEY, false).number ?: 0f get() = getProperty(Z_SIZE_KEY, false).number ?: 0f
set(value) { set(value) {
setItem(Z_SIZE_KEY, value.asValue()) setProperty(Z_SIZE_KEY, value.asValue())
} }
var value: Int var value: Int
get() = getProperty("value", false).int ?: 0 get() = getProperty("value", false).int ?: 0
set(value) { set(value) {
setItem("value", value.asValue()) setProperty("value", value.asValue())
val size = value.toFloat() / 255f * 20f val size = value.toFloat() / 255f * 20f
scaleZ = size scaleZ = size
z = size / 2 z = size / 2

View File

@ -1,6 +1,7 @@
import hep.dataforge.context.Global import hep.dataforge.context.Global
import hep.dataforge.js.Application import hep.dataforge.js.Application
import hep.dataforge.js.startApplication import hep.dataforge.js.startApplication
import hep.dataforge.meta.invoke
import hep.dataforge.vision.bootstrap.visionPropertyEditor import hep.dataforge.vision.bootstrap.visionPropertyEditor
import hep.dataforge.vision.react.ThreeCanvasComponent import hep.dataforge.vision.react.ThreeCanvasComponent
import hep.dataforge.vision.react.objectTree import hep.dataforge.vision.react.objectTree
@ -18,7 +19,7 @@ public fun RBuilder.threeCanvas(object3D: Solid, options: Canvas3DOptions.() ->
child(ThreeCanvasComponent) { child(ThreeCanvasComponent) {
attrs { attrs {
this.obj = object3D this.obj = object3D
this.options = Canvas3DOptions.invoke(options) this.options = Canvas3DOptions(options)
} }
} }
} }

View File

@ -17,7 +17,7 @@ public fun RBuilder.visionPropertyEditor(
key: Any? = null key: Any? = null
) { ) {
card("Properties") { card("Properties") {
configEditor(item, descriptor, default, key) configEditor(item.config, descriptor, default, key)
} }
val styles = item.styles val styles = item.styles
if(styles.isNotEmpty()) { if(styles.isNotEmpty()) {
@ -40,6 +40,6 @@ public fun Element.visionPropertyEditor(
item: Vision, item: Vision,
descriptor: NodeDescriptor? = item.descriptor, descriptor: NodeDescriptor? = item.descriptor,
default: Meta? = null default: Meta? = null
) = render(this) { ): Unit = render(this) {
visionPropertyEditor(item, descriptor, default) visionPropertyEditor(item, descriptor, default)
} }

View File

@ -233,10 +233,10 @@ public fun RBuilder.configEditor(config: Config, descriptor: NodeDescriptor? = n
} }
} }
} }
//
public fun RBuilder.configEditor( //public fun RBuilder.configEditor(
obj: Configurable, // obj: Configurable,
descriptor: NodeDescriptor? = obj.descriptor, // descriptor: NodeDescriptor?,
default: Meta? = null, // default: Meta? = null,
key: Any? = null // key: Any? = null
) = configEditor(obj.config,descriptor, default, key) //): Unit = configEditor(obj.config, descriptor, default, key)

View File

@ -1,6 +1,7 @@
package hep.dataforge.vision.react package hep.dataforge.vision.react
import hep.dataforge.context.Context import hep.dataforge.context.Context
import hep.dataforge.meta.empty
import hep.dataforge.names.Name import hep.dataforge.names.Name
import hep.dataforge.vision.solid.Solid import hep.dataforge.vision.solid.Solid
import hep.dataforge.vision.solid.specifications.Canvas3DOptions import hep.dataforge.vision.solid.specifications.Canvas3DOptions

View File

@ -1,24 +0,0 @@
package hep.dataforge.vision
import hep.dataforge.names.NameToken
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
@Serializable
@SerialName("vision.group")
public class SimpleVisionGroup : AbstractVisionGroup() {
@SerialName("children")
private val _children = HashMap<NameToken, Vision>()
override val children: Map<NameToken, Vision> get() = _children
override fun removeChild(token: NameToken) {
_children.remove(token)?.apply { parent = null }
}
override fun setChild(token: NameToken, child: Vision) {
_children[token] = child
}
override fun createGroup(): SimpleVisionGroup = SimpleVisionGroup()
}

View File

@ -2,6 +2,7 @@ package hep.dataforge.vision
import hep.dataforge.meta.* import hep.dataforge.meta.*
import hep.dataforge.meta.descriptors.Described import hep.dataforge.meta.descriptors.Described
import hep.dataforge.meta.descriptors.NodeDescriptor
import hep.dataforge.names.Name import hep.dataforge.names.Name
import hep.dataforge.names.asName import hep.dataforge.names.asName
import hep.dataforge.names.toName import hep.dataforge.names.toName
@ -70,6 +71,8 @@ public interface Vision : Configurable, Described {
*/ */
public fun update(change: Vision) public fun update(change: Vision)
override val descriptor: NodeDescriptor?
public companion object { public companion object {
public const val TYPE: String = "vision" public const val TYPE: String = "vision"
public val STYLE_KEY: Name = "@style".asName() public val STYLE_KEY: Name = "@style".asName()
@ -133,8 +136,7 @@ public fun Vision.property(
} }
} }
//TODO replace by value public fun Vision.properties(inherit: Boolean = true): MutableItemProvider = object : MutableItemProvider {
fun Vision.properties(inherit: Boolean = true): MutableItemProvider = object : MutableItemProvider {
override fun getItem(name: Name): MetaItem<*>? { override fun getItem(name: Name): MetaItem<*>? {
return getProperty(name, inherit) return getProperty(name, inherit)
} }

View File

@ -1,20 +1,27 @@
package hep.dataforge.vision package hep.dataforge.vision
import hep.dataforge.names.* import hep.dataforge.names.*
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import kotlinx.serialization.Transient import kotlinx.serialization.Transient
/** /**
* Abstract implementation of mutable group of [Vision] * Abstract implementation of mutable group of [Vision]
*/ */
public abstract class AbstractVisionGroup : VisionBase(), MutableVisionGroup { @Serializable
@SerialName("vision.group")
public open class VisionGroupBase : VisionBase(), MutableVisionGroup {
//protected abstract val _children: MutableMap<NameToken, T> //protected abstract val _children: MutableMap<NameToken, T>
@SerialName("children")
protected val childrenInternal = LinkedHashMap<NameToken, Vision>()
/** /**
* A map of top level named children * A map of top level named children
*/ */
abstract override val children: Map<NameToken, Vision> override val children: Map<NameToken, Vision> get() = childrenInternal
final override var styleSheet: StyleSheet? = null final override var styleSheet: StyleSheet? = null
private set private set
@ -24,7 +31,7 @@ public abstract class AbstractVisionGroup : VisionBase(), MutableVisionGroup {
*/ */
public open fun styleSheet(block: StyleSheet.() -> Unit) { public open fun styleSheet(block: StyleSheet.() -> Unit) {
if (styleSheet == null) { if (styleSheet == null) {
styleSheet = StyleSheet(this@AbstractVisionGroup) styleSheet = StyleSheet(this@VisionGroupBase)
} }
styleSheet!!.block() styleSheet!!.block()
} }
@ -70,12 +77,9 @@ public abstract class AbstractVisionGroup : VisionBase(), MutableVisionGroup {
/** /**
* Remove a child with given name token * Remove a child with given name token
*/ */
protected abstract fun removeChild(token: NameToken) public fun removeChild(token: NameToken) {
childrenInternal.remove(token)
/** }
* Add, remove or replace child with given name
*/
protected abstract fun setChild(token: NameToken, child: Vision)
/** /**
* Add a static child. Statics could not be found by name, removed or replaced. Changing statics also do not trigger events. * Add a static child. Statics could not be found by name, removed or replaced. Changing statics also do not trigger events.
@ -84,15 +88,15 @@ public abstract class AbstractVisionGroup : VisionBase(), MutableVisionGroup {
attach(NameToken("@static", index = child.hashCode().toString()), child) attach(NameToken("@static", index = child.hashCode().toString()), child)
} }
protected abstract fun createGroup(): AbstractVisionGroup protected open fun createGroup(): VisionGroupBase = VisionGroupBase()
/** /**
* Set parent for given child and attach it * Set parent for given child and attach it
*/ */
protected fun attach(token: NameToken, child: Vision) { private fun attach(token: NameToken, child: Vision) {
if (child.parent == null) { if (child.parent == null) {
child.parent = this child.parent = this
setChild(token, child) childrenInternal[token] = child
} else if (child.parent !== this) { } else if (child.parent !== this) {
error("Can't reassign existing parent for $child") error("Can't reassign existing parent for $child")
} }
@ -101,7 +105,7 @@ public abstract class AbstractVisionGroup : VisionBase(), MutableVisionGroup {
/** /**
* Recursively create a child group * Recursively create a child group
*/ */
private fun createGroups(name: Name): AbstractVisionGroup { private fun createGroups(name: Name): VisionGroupBase {
return when { return when {
name.isEmpty() -> error("Should be unreachable") name.isEmpty() -> error("Should be unreachable")
name.length == 1 -> { name.length == 1 -> {
@ -110,7 +114,7 @@ public abstract class AbstractVisionGroup : VisionBase(), MutableVisionGroup {
null -> createGroup().also { child -> null -> createGroup().also { child ->
attach(token, child) attach(token, child)
} }
is AbstractVisionGroup -> current is VisionGroupBase -> current
else -> error("Can't create group with name $name because it exists and not a group") else -> error("Can't create group with name $name because it exists and not a group")
} }
} }

View File

@ -83,7 +83,7 @@ public class VisionManager(meta: Meta) : AbstractPlugin(meta) {
private val defaultSerialModule: SerializersModule = SerializersModule { private val defaultSerialModule: SerializersModule = SerializersModule {
polymorphic(Vision::class) { polymorphic(Vision::class) {
subclass(SimpleVisionGroup.serializer()) subclass(VisionGroupBase.serializer())
} }
} }
} }

View File

@ -1,7 +1,7 @@
package hep.dataforge.vision package hep.dataforge.vision
import hep.dataforge.meta.* import hep.dataforge.meta.*
import hep.dataforge.meta.descriptors.ItemDescriptor import hep.dataforge.meta.descriptors.NodeDescriptor
import hep.dataforge.names.Name import hep.dataforge.names.Name
import hep.dataforge.names.NameToken import hep.dataforge.names.NameToken
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
@ -43,7 +43,7 @@ public object NullVision : Vision {
} }
override val config: Config get() = Config() override val config: Config get() = Config()
override val descriptor: ItemDescriptor? get() = null override val descriptor: NodeDescriptor? get() = null
} }
private fun Vision.collectChange(scope: CoroutineScope, collector: Vision): Job = scope.launch { private fun Vision.collectChange(scope: CoroutineScope, collector: Vision): Job = scope.launch {
@ -56,7 +56,7 @@ private fun Vision.collectChange(scope: CoroutineScope, collector: Vision): Job
//Subscribe for children changes //Subscribe for children changes
children.forEach { (token, child) -> children.forEach { (token, child) ->
val childCollector: Vision = if (child is VisionGroup) { val childCollector: Vision = if (child is VisionGroup) {
SimpleVisionGroup() VisionGroupBase()
} else { } else {
VisionBase() VisionBase()
} }
@ -94,7 +94,7 @@ public fun Vision.flowChanges(scope: CoroutineScope, collectionDuration: Duratio
emit(this@flowChanges) emit(this@flowChanges)
while (true) { while (true) {
val collector: Vision = if (this is VisionGroup) { val collector: Vision = if (this is VisionGroup) {
SimpleVisionGroup() VisionGroupBase()
} else { } else {
VisionBase() VisionBase()
} }

View File

@ -6,6 +6,7 @@ import hep.dataforge.meta.descriptors.NodeDescriptor
import hep.dataforge.meta.update import hep.dataforge.meta.update
import hep.dataforge.vision.Vision import hep.dataforge.vision.Vision
import hep.dataforge.vision.resolveStyle import hep.dataforge.vision.resolveStyle
import hep.dataforge.vision.setProperty
import javafx.beans.binding.Binding import javafx.beans.binding.Binding
import javafx.beans.property.SimpleObjectProperty import javafx.beans.property.SimpleObjectProperty
import javafx.scene.Node import javafx.scene.Node
@ -36,7 +37,7 @@ class VisualObjectEditorFragment(val selector: (Vision) -> Meta) : Fragment() {
val config = Config().apply { val config = Config().apply {
update(meta) update(meta)
onChange(this@VisualObjectEditorFragment) { key, _, after -> onChange(this@VisualObjectEditorFragment) { key, _, after ->
visualObject.setItem(key, after) visualObject.setProperty(key, after)
} }
} }
//remember old config reference to cleanup listeners //remember old config reference to cleanup listeners

View File

@ -11,6 +11,7 @@ import hep.dataforge.values.asValue
import hep.dataforge.vision.Vision import hep.dataforge.vision.Vision
import hep.dataforge.vision.Vision.Companion.VISIBLE_KEY import hep.dataforge.vision.Vision.Companion.VISIBLE_KEY
import hep.dataforge.vision.enum import hep.dataforge.vision.enum
import hep.dataforge.vision.setProperty
import hep.dataforge.vision.solid.Solid.Companion.DETAIL_KEY import hep.dataforge.vision.solid.Solid.Companion.DETAIL_KEY
import hep.dataforge.vision.solid.Solid.Companion.IGNORE_KEY import hep.dataforge.vision.solid.Solid.Companion.IGNORE_KEY
import hep.dataforge.vision.solid.Solid.Companion.LAYER_KEY import hep.dataforge.vision.solid.Solid.Companion.LAYER_KEY
@ -121,8 +122,8 @@ public enum class RotationOrder {
* Rotation order * Rotation order
*/ */
public var Solid.rotationOrder: RotationOrder public var Solid.rotationOrder: RotationOrder
get() = getItem(Solid.ROTATION_ORDER_KEY).enum<RotationOrder>() ?: RotationOrder.XYZ get() = getProperty(Solid.ROTATION_ORDER_KEY).enum<RotationOrder>() ?: RotationOrder.XYZ
set(value) = setValue(Solid.ROTATION_ORDER_KEY, value.name.asValue()) set(value) = setProperty(Solid.ROTATION_ORDER_KEY, value.name.asValue())
/** /**
@ -130,7 +131,7 @@ public var Solid.rotationOrder: RotationOrder
*/ */
public var Solid.detail: Int? public var Solid.detail: Int?
get() = getProperty(DETAIL_KEY, false).int get() = getProperty(DETAIL_KEY, false).int
set(value) = setValue(DETAIL_KEY, value?.asValue()) set(value) = setProperty(DETAIL_KEY, value?.asValue())
/** /**
* If this property is true, the object will be ignored on render. * If this property is true, the object will be ignored on render.
@ -138,7 +139,7 @@ public var Solid.detail: Int?
*/ */
public var Vision.ignore: Boolean? public var Vision.ignore: Boolean?
get() = getProperty(IGNORE_KEY, false).boolean get() = getProperty(IGNORE_KEY, false).boolean
set(value) = setValue(IGNORE_KEY, value?.asValue()) set(value) = setProperty(IGNORE_KEY, value?.asValue())
//var VisualObject.selected: Boolean? //var VisualObject.selected: Boolean?
// get() = getProperty(SELECTED_KEY).boolean // get() = getProperty(SELECTED_KEY).boolean

View File

@ -7,7 +7,6 @@ import hep.dataforge.names.NameToken
import hep.dataforge.vision.* import hep.dataforge.vision.*
import kotlinx.serialization.SerialName import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
import kotlin.collections.set
public interface PrototypeHolder { public interface PrototypeHolder {
public val parent: VisionGroup? public val parent: VisionGroup?
@ -19,7 +18,7 @@ public interface PrototypeHolder {
*/ */
@Serializable @Serializable
@SerialName("group.solid") @SerialName("group.solid")
public class SolidGroup : AbstractVisionGroup(), Solid, PrototypeHolder { public class SolidGroup : VisionGroupBase(), Solid, PrototypeHolder {
override val descriptor: NodeDescriptor get() = Solid.descriptor override val descriptor: NodeDescriptor get() = Solid.descriptor
@ -36,7 +35,7 @@ public class SolidGroup : AbstractVisionGroup(), Solid, PrototypeHolder {
public fun prototypes(builder: MutableVisionGroup.() -> Unit): Unit { public fun prototypes(builder: MutableVisionGroup.() -> Unit): Unit {
(prototypes ?: Prototypes().also { (prototypes ?: Prototypes().also {
prototypes = it prototypes = it
attach(it) it.parent = this
}).run(builder) }).run(builder)
} }
@ -49,23 +48,12 @@ public class SolidGroup : AbstractVisionGroup(), Solid, PrototypeHolder {
@Serializable(Point3DSerializer::class) @Serializable(Point3DSerializer::class)
override var scale: Point3D? = null override var scale: Point3D? = null
@SerialName("children")
private val _children = LinkedHashMap<NameToken, Vision>()
override val children: Map<NameToken, Vision> get() = _children
override fun attachChildren() { override fun attachChildren() {
prototypes?.parent = this prototypes?.parent = this
prototypes?.attachChildren() prototypes?.attachChildren()
super.attachChildren() super.attachChildren()
} }
override fun removeChild(token: NameToken) {
_children.remove(token)?.apply { parent = null }
}
override fun setChild(token: NameToken, child: Vision) {
_children[token] = child
}
// /** // /**
// * TODO add special static group to hold statics without propagation // * TODO add special static group to hold statics without propagation
@ -103,25 +91,15 @@ public fun MutableVisionGroup.group(name: String, action: SolidGroup.() -> Unit
/** /**
* A special class which works as a holder for prototypes * A special class which works as a holder for prototypes
*/ */
@Serializable(PrototypesSerializer::class)
internal class Prototypes( internal class Prototypes(
override var children: MutableMap<NameToken, Vision> = LinkedHashMap(), override var children: MutableMap<NameToken, Vision> = LinkedHashMap(),
) : AbstractVisionGroup(), MutableVisionGroup, PrototypeHolder { ) : VisionGroupBase(), PrototypeHolder {
override fun styleSheet(block: StyleSheet.() -> Unit) { override fun styleSheet(block: StyleSheet.() -> Unit) {
error("Can't define stylesheet for prototypes block") error("Can't define stylesheet for prototypes block")
} }
override fun removeChild(token: NameToken) {
children.remove(token)
childrenChanged(token, null)
}
override fun setChild(token: NameToken, child: Vision) {
children[token] = child
}
override fun createGroup() = SimpleVisionGroup()
override var properties: Config? override var properties: Config?
get() = null get() = null
set(_) { set(_) {

View File

@ -4,12 +4,12 @@ import hep.dataforge.context.AbstractPlugin
import hep.dataforge.context.Context import hep.dataforge.context.Context
import hep.dataforge.context.PluginFactory import hep.dataforge.context.PluginFactory
import hep.dataforge.context.PluginTag import hep.dataforge.context.PluginTag
import hep.dataforge.meta.* import hep.dataforge.meta.Meta
import hep.dataforge.names.Name import hep.dataforge.names.Name
import hep.dataforge.names.toName import hep.dataforge.names.toName
import hep.dataforge.vision.SimpleVisionGroup
import hep.dataforge.vision.Vision import hep.dataforge.vision.Vision
import hep.dataforge.vision.VisionGroup import hep.dataforge.vision.VisionGroup
import hep.dataforge.vision.VisionGroupBase
import hep.dataforge.vision.VisionManager import hep.dataforge.vision.VisionManager
import hep.dataforge.vision.VisionManager.Companion.VISION_SERIAL_MODULE_TARGET import hep.dataforge.vision.VisionManager.Companion.VISION_SERIAL_MODULE_TARGET
import kotlinx.serialization.json.Json import kotlinx.serialization.json.Json
@ -51,7 +51,7 @@ public class SolidManager(meta: Meta) : AbstractPlugin(meta) {
contextual(Point2DSerializer) contextual(Point2DSerializer)
polymorphic(Vision::class) { polymorphic(Vision::class) {
subclass(SimpleVisionGroup.serializer()) subclass(VisionGroupBase.serializer())
solids() solids()
} }

View File

@ -9,6 +9,7 @@ import hep.dataforge.names.plus
import hep.dataforge.values.ValueType import hep.dataforge.values.ValueType
import hep.dataforge.values.asValue import hep.dataforge.values.asValue
import hep.dataforge.vision.Colors import hep.dataforge.vision.Colors
import hep.dataforge.vision.setProperty
import hep.dataforge.vision.solid.SolidMaterial.Companion.MATERIAL_COLOR_KEY import hep.dataforge.vision.solid.SolidMaterial.Companion.MATERIAL_COLOR_KEY
import hep.dataforge.vision.solid.SolidMaterial.Companion.MATERIAL_KEY import hep.dataforge.vision.solid.SolidMaterial.Companion.MATERIAL_KEY
import hep.dataforge.vision.solid.SolidMaterial.Companion.MATERIAL_OPACITY_KEY import hep.dataforge.vision.solid.SolidMaterial.Companion.MATERIAL_OPACITY_KEY
@ -48,7 +49,7 @@ public class SolidMaterial : Scheme() {
internal val WIREFRAME_KEY = "wireframe".asName() internal val WIREFRAME_KEY = "wireframe".asName()
public val MATERIAL_WIREFRAME_KEY: Name = MATERIAL_KEY + WIREFRAME_KEY public val MATERIAL_WIREFRAME_KEY: Name = MATERIAL_KEY + WIREFRAME_KEY
public val descriptor: NodeDescriptor by lazy { public override val descriptor: NodeDescriptor by lazy {
//must be lazy to avoid initialization bug //must be lazy to avoid initialization bug
NodeDescriptor { NodeDescriptor {
value(COLOR_KEY) { value(COLOR_KEY) {
@ -79,17 +80,17 @@ public class SolidMaterial : Scheme() {
* Set color as web-color * Set color as web-color
*/ */
public fun Solid.color(webColor: String) { public fun Solid.color(webColor: String) {
setItem(MATERIAL_COLOR_KEY, webColor.asValue()) setProperty(MATERIAL_COLOR_KEY, webColor.asValue())
} }
/** /**
* Set color as integer * Set color as integer
*/ */
public fun Solid.color(rgb: Int) { public fun Solid.color(rgb: Int) {
setItem(MATERIAL_COLOR_KEY, rgb.asValue()) setProperty(MATERIAL_COLOR_KEY, rgb.asValue())
} }
public fun Solid.color(r: UByte, g: UByte, b: UByte): Unit = setItem( public fun Solid.color(r: UByte, g: UByte, b: UByte): Unit = setProperty(
MATERIAL_COLOR_KEY, MATERIAL_COLOR_KEY,
Colors.rgbToString(r, g, b).asValue() Colors.rgbToString(r, g, b).asValue()
) )
@ -98,13 +99,13 @@ public fun Solid.color(r: UByte, g: UByte, b: UByte): Unit = setItem(
* Web colors representation of the color in `#rrggbb` format or HTML name * Web colors representation of the color in `#rrggbb` format or HTML name
*/ */
public var Solid.color: String? public var Solid.color: String?
get() = getItem(MATERIAL_COLOR_KEY)?.let { Colors.fromMeta(it) } get() = getProperty(MATERIAL_COLOR_KEY)?.let { Colors.fromMeta(it) }
set(value) { set(value) {
setItem(MATERIAL_COLOR_KEY, value?.asValue()) setProperty(MATERIAL_COLOR_KEY, value?.asValue())
} }
public val Solid.material: SolidMaterial? public val Solid.material: SolidMaterial?
get() = getItem(MATERIAL_KEY).node?.let { SolidMaterial.wrap(it) } get() = getProperty(MATERIAL_KEY).node?.let { SolidMaterial.wrap(it) }
public fun Solid.material(builder: SolidMaterial.() -> Unit) { public fun Solid.material(builder: SolidMaterial.() -> Unit) {
val node = config[MATERIAL_KEY].node val node = config[MATERIAL_KEY].node
@ -116,7 +117,7 @@ public fun Solid.material(builder: SolidMaterial.() -> Unit) {
} }
public var Solid.opacity: Double? public var Solid.opacity: Double?
get() = getItem(MATERIAL_OPACITY_KEY).double get() = getProperty(MATERIAL_OPACITY_KEY).double
set(value) { set(value) {
setItem(MATERIAL_OPACITY_KEY, value?.asValue()) setProperty(MATERIAL_OPACITY_KEY, value?.asValue())
} }

View File

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

View File

@ -85,9 +85,9 @@ fun Mesh.applyProperties(obj: Solid): Mesh = apply{
fun Mesh.applyEdges(obj: Solid) { fun Mesh.applyEdges(obj: Solid) {
val edges = children.find { it.name == "@edges" } as? LineSegments val edges = children.find { it.name == "@edges" } as? LineSegments
//inherited edges definition, enabled by default //inherited edges definition, enabled by default
if (obj.getItem(MeshThreeFactory.EDGES_ENABLED_KEY).boolean != false) { if (obj.getProperty(MeshThreeFactory.EDGES_ENABLED_KEY).boolean != false) {
val bufferGeometry = geometry as? BufferGeometry ?: return val bufferGeometry = geometry as? BufferGeometry ?: return
val material = ThreeMaterials.getLineMaterial(obj.getItem(MeshThreeFactory.EDGES_MATERIAL_KEY).node, true) val material = ThreeMaterials.getLineMaterial(obj.getProperty(MeshThreeFactory.EDGES_MATERIAL_KEY).node, true)
if (edges == null) { if (edges == null) {
add( add(
LineSegments( LineSegments(
@ -114,9 +114,9 @@ fun Mesh.applyWireFrame(obj: Solid) {
(it as LineSegments).dispose() (it as LineSegments).dispose()
} }
//inherited wireframe definition, disabled by default //inherited wireframe definition, disabled by default
if (obj.getItem(MeshThreeFactory.WIREFRAME_ENABLED_KEY).boolean == true) { if (obj.getProperty(MeshThreeFactory.WIREFRAME_ENABLED_KEY).boolean == true) {
val bufferGeometry = geometry as? BufferGeometry ?: return val bufferGeometry = geometry as? BufferGeometry ?: return
val material = ThreeMaterials.getLineMaterial(obj.getItem(MeshThreeFactory.WIREFRAME_MATERIAL_KEY).node, true) val material = ThreeMaterials.getLineMaterial(obj.getProperty(MeshThreeFactory.WIREFRAME_MATERIAL_KEY).node, true)
add( add(
LineSegments( LineSegments(
WireframeGeometry(bufferGeometry), WireframeGeometry(bufferGeometry),

View File

@ -1,9 +1,7 @@
package hep.dataforge.vision.solid.three package hep.dataforge.vision.solid.three
import hep.dataforge.context.Context import hep.dataforge.context.Context
import hep.dataforge.meta.Meta import hep.dataforge.meta.*
import hep.dataforge.meta.getItem
import hep.dataforge.meta.string
import hep.dataforge.names.Name import hep.dataforge.names.Name
import hep.dataforge.names.plus import hep.dataforge.names.plus
import hep.dataforge.names.toName import hep.dataforge.names.toName
@ -275,4 +273,4 @@ public fun ThreePlugin.render(
obj: Solid, obj: Solid,
onSelect: ((Name?) -> Unit)? = null, onSelect: ((Name?) -> Unit)? = null,
options: Canvas3DOptions.() -> Unit = {}, options: Canvas3DOptions.() -> Unit = {},
): Unit = output(element, Canvas3DOptions(options), onSelect).render(obj) ): Unit = output(element, Canvas3DOptions.invoke(options), onSelect).render(obj)

View File

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

View File

@ -12,23 +12,22 @@ import info.laht.threekt.materials.MeshPhongMaterial
import info.laht.threekt.math.Color import info.laht.threekt.math.Color
object ThreeMaterials { public object ThreeMaterials {
val DEFAULT_COLOR = Color(Colors.darkgreen) public val DEFAULT_COLOR: Color = Color(Colors.darkgreen)
val DEFAULT = MeshBasicMaterial().apply { public val DEFAULT: MeshBasicMaterial = MeshBasicMaterial().apply {
color.set(DEFAULT_COLOR) color.set(DEFAULT_COLOR)
} }
val DEFAULT_LINE_COLOR = Color(Colors.black) public val DEFAULT_LINE_COLOR: Color = Color(Colors.black)
val DEFAULT_LINE = LineBasicMaterial().apply { public val DEFAULT_LINE: LineBasicMaterial = LineBasicMaterial().apply {
color.set(DEFAULT_LINE_COLOR) color.set(DEFAULT_LINE_COLOR)
} }
val SELECTED_MATERIAL = LineBasicMaterial().apply { public val SELECTED_MATERIAL: LineBasicMaterial = LineBasicMaterial().apply {
color.set(Colors.ivory) color.set(Colors.ivory)
linewidth = 8.0 linewidth = 8.0
} }
public val HIGHLIGHT_MATERIAL: LineBasicMaterial = LineBasicMaterial().apply {
val HIGHLIGHT_MATERIAL = LineBasicMaterial().apply {
color.set(Colors.blue) color.set(Colors.blue)
linewidth = 8.0 linewidth = 8.0
} }
@ -75,7 +74,7 @@ object ThreeMaterials {
} }
fun getMaterial(vision3D: Vision, cache: Boolean): Material { fun getMaterial(vision3D: Vision, cache: Boolean): Material {
val meta = vision3D.getItem(SolidMaterial.MATERIAL_KEY).node ?: return DEFAULT val meta = vision3D.getProperty(SolidMaterial.MATERIAL_KEY).node ?: return DEFAULT
return if (cache) { return if (cache) {
materialCache.getOrPut(meta) { buildMaterial(meta) } materialCache.getOrPut(meta) { buildMaterial(meta) }
} else { } else {

View File

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

View File

@ -3,6 +3,7 @@ package hep.dataforge.vision.solid.fx
import hep.dataforge.context.Context import hep.dataforge.context.Context
import hep.dataforge.context.ContextAware import hep.dataforge.context.ContextAware
import hep.dataforge.meta.Meta import hep.dataforge.meta.Meta
import hep.dataforge.meta.empty
import hep.dataforge.output.Renderer import hep.dataforge.output.Renderer
import hep.dataforge.vision.solid.Solid import hep.dataforge.vision.solid.Solid
import hep.dataforge.vision.solid.specifications.Canvas3DOptions import hep.dataforge.vision.solid.specifications.Canvas3DOptions

View File

@ -34,7 +34,7 @@ class VisualObjectFXBinding(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.getItem(key) override fun computeValue(): MetaItem<*>? = obj.getProperty(key)
} }
} }
} }