From 8f1dcac6cdb997ddc90423a4c163e5ab7ed66415 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Tue, 20 Aug 2019 13:39:10 +0300 Subject: [PATCH] Fixed after migration to new Group structure --- .../vis/common/AbstractVisualGroup.kt | 33 +++++-- .../vis/common/AbstractVisualObject.kt | 3 +- .../hep/dataforge/vis/common/VisualGroup.kt | 2 +- .../dataforge/vis/spatial/gdml/visualGDML.kt | 9 +- .../kotlin/hep/dataforge/vis/spatial/Box.kt | 2 +- .../dataforge/vis/spatial/Visual3DPlugin.kt | 10 ++ .../dataforge/vis/spatial/VisualGroup3D.kt | 92 +++++++++++++++++++ .../dataforge/vis/spatial/VisualObject3D.kt | 70 +------------- .../hep/dataforge/vis/spatial/serilization.kt | 18 +++- .../dataforge/vis/spatial/three/Materials.kt | 2 +- .../vis/spatial/three/ThreeFactory.kt | 2 +- .../vis/spatial/three/ThreePlugin.kt | 13 ++- 12 files changed, 167 insertions(+), 89 deletions(-) create mode 100644 dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/VisualGroup3D.kt diff --git a/dataforge-vis-common/src/commonMain/kotlin/hep/dataforge/vis/common/AbstractVisualGroup.kt b/dataforge-vis-common/src/commonMain/kotlin/hep/dataforge/vis/common/AbstractVisualGroup.kt index 939a2ec6..23b889f6 100644 --- a/dataforge-vis-common/src/commonMain/kotlin/hep/dataforge/vis/common/AbstractVisualGroup.kt +++ b/dataforge-vis-common/src/commonMain/kotlin/hep/dataforge/vis/common/AbstractVisualGroup.kt @@ -54,10 +54,24 @@ abstract class AbstractVisualGroup : AbstractVisualObject(), VisualGroup { // // } + /** + * Remove a child with given name token + */ protected abstract fun removeChild(token: NameToken) + /** + * Add, remove or replace child with given name + */ protected abstract fun setChild(token: NameToken, child: VisualObject?) + /** + * Add a static child. Statics could not be found by name, removed or replaced + */ + protected abstract fun addStatic(child: VisualObject) + + /** + * Recursively create a child group + */ protected abstract fun createGroup(name: Name): VisualGroup /** @@ -66,17 +80,16 @@ abstract class AbstractVisualGroup : AbstractVisualObject(), VisualGroup { */ override fun set(name: Name, child: VisualObject?) { when { - name.isEmpty() -> error("") + name.isEmpty() -> { + if (child != null) { + addStatic(child) + } + } name.length == 1 -> { val token = name.first()!! if (child == null) { removeChild(token) } else { - if (child.parent == null) { - child.parent = this - } else { - error("Can't reassign existing parent for $child") - } setChild(token, child) } } @@ -89,7 +102,13 @@ abstract class AbstractVisualGroup : AbstractVisualObject(), VisualGroup { listeners.forEach { it.callback(name, child) } } - operator fun set(key: String, child: VisualObject?) = set(key.asName(), child) + operator fun set(key: String, child: VisualObject?) = if (key.isBlank()) { + child?.let { addStatic(child) } + } else { + set(key.asName(), child) + } + + operator fun set(key: String?, child: VisualObject?) = set(key ?: "", child) protected fun MetaBuilder.updateChildren() { //adding named children diff --git a/dataforge-vis-common/src/commonMain/kotlin/hep/dataforge/vis/common/AbstractVisualObject.kt b/dataforge-vis-common/src/commonMain/kotlin/hep/dataforge/vis/common/AbstractVisualObject.kt index 61ae9b7c..7b3b7a89 100644 --- a/dataforge-vis-common/src/commonMain/kotlin/hep/dataforge/vis/common/AbstractVisualObject.kt +++ b/dataforge-vis-common/src/commonMain/kotlin/hep/dataforge/vis/common/AbstractVisualObject.kt @@ -34,8 +34,7 @@ abstract class AbstractVisualObject : VisualObject { abstract var properties: Config? override val config: Config get() = properties ?: Config().also { config -> - properties = config - config.onChange(this, ::propertyChanged) + properties = config.apply { onChange(this, ::propertyChanged) } } override fun setProperty(name: Name, value: Any?) { diff --git a/dataforge-vis-common/src/commonMain/kotlin/hep/dataforge/vis/common/VisualGroup.kt b/dataforge-vis-common/src/commonMain/kotlin/hep/dataforge/vis/common/VisualGroup.kt index 749938bd..2be37102 100644 --- a/dataforge-vis-common/src/commonMain/kotlin/hep/dataforge/vis/common/VisualGroup.kt +++ b/dataforge-vis-common/src/commonMain/kotlin/hep/dataforge/vis/common/VisualGroup.kt @@ -50,4 +50,4 @@ interface VisualGroup : VisualObject, Provider, Iterable { operator fun set(name: Name, child: VisualObject?) } -operator fun VisualGroup.get(str: String) = get(str.toName()) \ No newline at end of file +operator fun VisualGroup.get(str: String?) = get(str?.toName() ?: EmptyName) \ No newline at end of file diff --git a/dataforge-vis-spatial-gdml/src/commonMain/kotlin/hep/dataforge/vis/spatial/gdml/visualGDML.kt b/dataforge-vis-spatial-gdml/src/commonMain/kotlin/hep/dataforge/vis/spatial/gdml/visualGDML.kt index db513ba7..f71b4948 100644 --- a/dataforge-vis-spatial-gdml/src/commonMain/kotlin/hep/dataforge/vis/spatial/gdml/visualGDML.kt +++ b/dataforge-vis-spatial-gdml/src/commonMain/kotlin/hep/dataforge/vis/spatial/gdml/visualGDML.kt @@ -1,8 +1,10 @@ package hep.dataforge.vis.spatial.gdml import hep.dataforge.meta.Meta +import hep.dataforge.names.EmptyName import hep.dataforge.names.plus import hep.dataforge.vis.common.asName +import hep.dataforge.vis.common.get import hep.dataforge.vis.spatial.* import scientifik.gdml.* import kotlin.math.cos @@ -42,7 +44,7 @@ private inline operator fun Number.times(f: Float) = toFloat() * f private fun VisualGroup3D.addSolid( context: GDMLTransformer, solid: GDMLSolid, - name: String? = null, + name: String = "", block: VisualObject3D.() -> Unit = {} ): VisualObject3D { context.solidAdded(solid) @@ -185,7 +187,8 @@ private fun VisualGroup3D.addDivisionVolume( ?: error("Volume with ref ${divisionVolume.volumeref.ref} could not be resolved") //TODO add divisions - add( + set( + EmptyName, volume( context, volume @@ -217,7 +220,7 @@ private fun volume( } } GDMLTransformer.Action.CACHE -> { - if (context.templates[solid.name] == null) { + if (context.templates.get(solid.name) == null) { context.templates.addSolid(context, solid, solid.name) { this.material = context.resolveColor(group, material, solid) } diff --git a/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/Box.kt b/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/Box.kt index 40ee092d..4d0f05be 100644 --- a/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/Box.kt +++ b/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/Box.kt @@ -12,7 +12,7 @@ import kotlinx.serialization.UseSerializers import kotlin.reflect.KClass @Serializable -data class Box( +class Box( val xSize: Float, val ySize: Float, val zSize: Float diff --git a/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/Visual3DPlugin.kt b/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/Visual3DPlugin.kt index 2c9a0595..6057f628 100644 --- a/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/Visual3DPlugin.kt +++ b/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/Visual3DPlugin.kt @@ -3,12 +3,16 @@ package hep.dataforge.vis.spatial import hep.dataforge.context.AbstractPlugin import hep.dataforge.context.PluginFactory import hep.dataforge.context.PluginTag +import hep.dataforge.io.ConfigSerializer +import hep.dataforge.io.MetaSerializer +import hep.dataforge.io.NameSerializer import hep.dataforge.meta.* import hep.dataforge.names.Name import hep.dataforge.vis.common.VisualPlugin import kotlinx.serialization.json.Json import kotlinx.serialization.json.JsonConfiguration import kotlinx.serialization.modules.SerializersModule +import kotlinx.serialization.modules.contextual import kotlin.reflect.KClass class Visual3DPlugin(meta: Meta) : AbstractPlugin(meta) { @@ -28,6 +32,12 @@ class Visual3DPlugin(meta: Meta) : AbstractPlugin(meta) { override fun invoke(meta: Meta): Visual3DPlugin = Visual3DPlugin(meta) val serialModule = SerializersModule { + contextual(Point3DSerializer) + contextual(Point2DSerializer) + contextual(NameSerializer) + contextual(NameTokenSerializer) + contextual(MetaSerializer) + contextual(ConfigSerializer) polymorphic(VisualObject3D::class) { VisualGroup3D::class with VisualGroup3D.serializer() Proxy::class with Proxy.serializer() diff --git a/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/VisualGroup3D.kt b/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/VisualGroup3D.kt new file mode 100644 index 00000000..ea0837b3 --- /dev/null +++ b/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/VisualGroup3D.kt @@ -0,0 +1,92 @@ +@file:UseSerializers(Point3DSerializer::class, ConfigSerializer::class, NameTokenSerializer::class) +package hep.dataforge.vis.spatial + +import hep.dataforge.io.ConfigSerializer +import hep.dataforge.meta.Config +import hep.dataforge.meta.Configurable +import hep.dataforge.meta.MetaBuilder +import hep.dataforge.meta.set +import hep.dataforge.names.Name +import hep.dataforge.names.NameToken +import hep.dataforge.names.asName +import hep.dataforge.names.isEmpty +import hep.dataforge.vis.common.AbstractVisualGroup +import hep.dataforge.vis.common.VisualObject +import kotlinx.serialization.Serializable +import kotlinx.serialization.UseSerializers + +@Serializable +class VisualGroup3D : AbstractVisualGroup(), VisualObject3D, Configurable { + /** + * A container for templates visible inside this group + */ + var templates: VisualGroup3D? = null + set(value) { + value?.parent = this + field = value + } + + @Serializable(ConfigSerializer::class) + override var properties: Config? = null + + override var position: Point3D? = null + override var rotation: Point3D? = null + override var scale: Point3D? = null + + private val _children = HashMap() + override val children: Map get() = _children + + override fun removeChild(token: NameToken) { + _children.remove(token) + } + + override fun setChild(token: NameToken, child: VisualObject?) { + if (child == null) { + _children.remove(token) + } else { + if (child.parent == null) { + child.parent = this + } else { + error("Can't reassign existing parent for $child") + } + _children[token] = child + } + } + + /** + * TODO add special static group to hold statics without propagation + */ + override fun addStatic(child: VisualObject) = setChild(NameToken(child.hashCode().toString()), child) + + override fun createGroup(name: Name): VisualGroup3D { + return when { + name.isEmpty() -> error("Should be unreachable") + name.length == 1 -> { + val token = name.first()!! + when (val current = children[token]) { + null -> VisualGroup3D().also { setChild(token, it) } + is VisualGroup3D -> current + else -> error("Can't create group with name $name because it exists and not a group") + } + } + else -> createGroup(name.first()!!.asName()).createGroup(name.cutFirst()) + } + } + + fun getTemplate(name: Name): VisualObject3D? = + templates?.get(name) as? VisualObject3D + ?: (parent as? VisualGroup3D)?.getTemplate(name) + + override fun MetaBuilder.updateMeta() { + set(TEMPLATES_KEY, templates?.toMeta()) + updatePosition() + updateChildren() + } + + companion object { + const val TEMPLATES_KEY = "templates" + } +} + +fun VisualGroup3D.group(key: String = "", action: VisualGroup3D.() -> Unit = {}): VisualGroup3D = + VisualGroup3D().apply(action).also { set(key, it) } diff --git a/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/VisualObject3D.kt b/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/VisualObject3D.kt index 564349bc..b873eed2 100644 --- a/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/VisualObject3D.kt +++ b/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/VisualObject3D.kt @@ -2,18 +2,15 @@ package hep.dataforge.vis.spatial -import hep.dataforge.io.ConfigSerializer import hep.dataforge.io.NameSerializer import hep.dataforge.meta.* -import hep.dataforge.names.* +import hep.dataforge.names.plus import hep.dataforge.output.Output -import hep.dataforge.vis.common.AbstractVisualGroup import hep.dataforge.vis.common.VisualObject import hep.dataforge.vis.common.asName import hep.dataforge.vis.spatial.VisualObject3D.Companion.DETAIL_KEY import hep.dataforge.vis.spatial.VisualObject3D.Companion.MATERIAL_KEY import hep.dataforge.vis.spatial.VisualObject3D.Companion.VISIBLE_KEY -import kotlinx.serialization.Serializable import kotlinx.serialization.UseSerializers interface VisualObject3D : VisualObject { @@ -64,71 +61,6 @@ interface VisualObject3D : VisualObject { } } -@Serializable -class VisualGroup3D : AbstractVisualGroup(), VisualObject3D, Configurable { - /** - * A container for templates visible inside this group - */ - var templates: VisualGroup3D? = null - set(value) { - value?.parent = this - field = value - } - - @Serializable(ConfigSerializer::class) - override var properties: Config? = null - - override var position: Point3D? = null - override var rotation: Point3D? = null - override var scale: Point3D? = null - - private val _children = HashMap() - override val children: Map get() = _children - - override fun removeChild(token: NameToken) { - _children.remove(token) - } - - override fun setChild(token: NameToken, child: VisualObject?) { - if (child == null) { - _children.remove(token) - } else { - _children[token] = child - } - } - - override fun createGroup(name: Name): VisualGroup3D { - return when{ - name.isEmpty() -> error("Should be unreachable") - name.length == 1 -> { - val token = name.first()!! - when (val current = children[token]) { - null -> VisualGroup3D().also { setChild(token, it) } - is VisualGroup3D -> current - else -> error("Can't create group with name $name because it exists and not a group") - } - } - else -> createGroup(name.first()!!.asName()).createGroup(name.cutFirst()) - } - } - - fun getTemplate(name: Name): VisualObject3D? = - templates?.get(name) as? VisualGroup3D ?: (parent as? VisualGroup3D)?.getTemplate(name) - - override fun MetaBuilder.updateMeta() { - set(TEMPLATES_KEY, templates?.toMeta()) - updatePosition() - updateChildren() - } - - companion object { - const val TEMPLATES_KEY = "templates" - } -} - -fun VisualGroup3D.group(key: String = "", action: VisualGroup3D.() -> Unit = {}): VisualGroup3D = - VisualGroup3D().apply(action).also { set(key, it) } - fun Output.render(meta: Meta = EmptyMeta, action: VisualGroup3D.() -> Unit) = render(VisualGroup3D().apply(action), meta) diff --git a/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/serilization.kt b/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/serilization.kt index ffa92ae6..c7b3cbfa 100644 --- a/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/serilization.kt +++ b/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/serilization.kt @@ -1,7 +1,9 @@ package hep.dataforge.vis.spatial import hep.dataforge.names.NameToken +import hep.dataforge.names.toName import kotlinx.serialization.* +import kotlinx.serialization.internal.StringDescriptor @Serializable private data class Point2DSerial(val x: Double, val y: Double) @@ -10,7 +12,7 @@ private data class Point2DSerial(val x: Double, val y: Double) private data class Point3DSerial(val x: Double, val y: Double, val z: Double) @Serializer(Point3D::class) -object Point3DSerializer : KSerializer{ +object Point3DSerializer : KSerializer { private val serializer = Point3DSerial.serializer() override val descriptor: SerialDescriptor get() = serializer.descriptor @@ -26,7 +28,7 @@ object Point3DSerializer : KSerializer{ } @Serializer(Point2D::class) -object Point2DSerializer : KSerializer{ +object Point2DSerializer : KSerializer { private val serializer = Point2DSerial.serializer() override val descriptor: SerialDescriptor get() = serializer.descriptor @@ -42,4 +44,14 @@ object Point2DSerializer : KSerializer{ } @Serializer(NameToken::class) -object NameTokenSerializer : KSerializer \ No newline at end of file +object NameTokenSerializer : KSerializer { + override val descriptor: SerialDescriptor = StringDescriptor.withName("NameToken") + + override fun deserialize(decoder: Decoder): NameToken { + return decoder.decodeString().toName().first()!! + } + + override fun serialize(encoder: Encoder, obj: NameToken) { + encoder.encodeString(obj.toString()) + } +} \ No newline at end of file diff --git a/dataforge-vis-spatial/src/jsMain/kotlin/hep/dataforge/vis/spatial/three/Materials.kt b/dataforge-vis-spatial/src/jsMain/kotlin/hep/dataforge/vis/spatial/three/Materials.kt index 3d7f382b..523fd1ec 100644 --- a/dataforge-vis-spatial/src/jsMain/kotlin/hep/dataforge/vis/spatial/three/Materials.kt +++ b/dataforge-vis-spatial/src/jsMain/kotlin/hep/dataforge/vis/spatial/three/Materials.kt @@ -56,7 +56,7 @@ fun Meta?.jsMaterial(): Material { opacity = get("opacity")?.double ?: 1.0 transparent = get("transparent").boolean ?: (opacity < 1.0) //node["specularColor"]?.let { specular = it.color() } - side = 2 + //side = 2 } } } diff --git a/dataforge-vis-spatial/src/jsMain/kotlin/hep/dataforge/vis/spatial/three/ThreeFactory.kt b/dataforge-vis-spatial/src/jsMain/kotlin/hep/dataforge/vis/spatial/three/ThreeFactory.kt index 1b93b1bc..8d39a08f 100644 --- a/dataforge-vis-spatial/src/jsMain/kotlin/hep/dataforge/vis/spatial/three/ThreeFactory.kt +++ b/dataforge-vis-spatial/src/jsMain/kotlin/hep/dataforge/vis/spatial/three/ThreeFactory.kt @@ -90,7 +90,7 @@ abstract class MeshThreeFactory(override val type: KClass(obj) { buildGeometry(it) } + return buildMesh(obj) { buildGeometry(it) } } companion object { diff --git a/dataforge-vis-spatial/src/jsMain/kotlin/hep/dataforge/vis/spatial/three/ThreePlugin.kt b/dataforge-vis-spatial/src/jsMain/kotlin/hep/dataforge/vis/spatial/three/ThreePlugin.kt index da642588..9bd40342 100644 --- a/dataforge-vis-spatial/src/jsMain/kotlin/hep/dataforge/vis/spatial/three/ThreePlugin.kt +++ b/dataforge-vis-spatial/src/jsMain/kotlin/hep/dataforge/vis/spatial/three/ThreePlugin.kt @@ -5,6 +5,9 @@ import hep.dataforge.context.PluginFactory import hep.dataforge.context.PluginTag import hep.dataforge.context.content import hep.dataforge.meta.* +import hep.dataforge.names.Name +import hep.dataforge.names.asName +import hep.dataforge.names.isEmpty import hep.dataforge.vis.spatial.* import info.laht.threekt.cameras.Camera import info.laht.threekt.cameras.PerspectiveCamera @@ -46,7 +49,7 @@ class ThreePlugin : AbstractPlugin() { object3D.name = name.toString() group.add(object3D) } catch (ex: Throwable) { - console.error(ex) +// console.error(ex) logger.error(ex) { "Failed to render $name" } } } @@ -97,4 +100,12 @@ class ThreePlugin : AbstractPlugin() { override val type = ThreePlugin::class override fun invoke(meta: Meta) = ThreePlugin() } +} + +fun Object3D.findChild(name: Name): Object3D? { + return when { + name.isEmpty() -> this + name.length == 1 -> this.children.find { it.name == name.first()!!.toString() } + else -> findChild(name.first()!!.asName())?.findChild(name.cutFirst()) + } } \ No newline at end of file