Fixed after migration to new Group structure

This commit is contained in:
Alexander Nozik 2019-08-20 13:39:10 +03:00
parent 589afaa9b8
commit 8f1dcac6cd
12 changed files with 167 additions and 89 deletions

View File

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

View File

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

View File

@ -50,4 +50,4 @@ interface VisualGroup : VisualObject, Provider, Iterable<VisualObject> {
operator fun set(name: Name, child: VisualObject?)
}
operator fun VisualGroup.get(str: String) = get(str.toName())
operator fun VisualGroup.get(str: String?) = get(str?.toName() ?: EmptyName)

View File

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

View File

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

View File

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

View File

@ -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<NameToken, VisualObject>()
override val children: Map<NameToken, VisualObject> 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) }

View File

@ -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<NameToken, VisualObject>()
override val children: Map<NameToken, VisualObject> 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<VisualObject3D>.render(meta: Meta = EmptyMeta, action: VisualGroup3D.() -> Unit) =
render(VisualGroup3D().apply(action), meta)

View File

@ -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)
@ -42,4 +44,14 @@ object Point2DSerializer : KSerializer<Point2D>{
}
@Serializer(NameToken::class)
object NameTokenSerializer : KSerializer<NameToken>
object NameTokenSerializer : KSerializer<NameToken> {
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())
}
}

View File

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

View File

@ -90,7 +90,7 @@ abstract class MeshThreeFactory<T : VisualObject3D>(override val type: KClass<ou
override fun invoke(obj: T): Mesh {
//create mesh from geometry
return buildMesh<T>(obj) { buildGeometry(it) }
return buildMesh(obj) { buildGeometry(it) }
}
companion object {

View File

@ -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" }
}
}
@ -98,3 +101,11 @@ class ThreePlugin : AbstractPlugin() {
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())
}
}