Fix proxy child property update issue on Three. Name refactoring.

This commit is contained in:
Alexander Nozik 2020-03-01 11:00:43 +03:00
parent 6b455b57aa
commit ab47652314
21 changed files with 126 additions and 48 deletions

View File

@ -13,7 +13,7 @@ interface VisualFactory<T : VisualObject> {
): T ): T
} }
class VisualPlugin(meta: Meta) : AbstractPlugin(meta) { class Visual(meta: Meta) : AbstractPlugin(meta) {
override val tag: PluginTag get() = Companion.tag override val tag: PluginTag get() = Companion.tag
/** /**
@ -27,11 +27,11 @@ class VisualPlugin(meta: Meta) : AbstractPlugin(meta) {
return visualFactories[T::class]?.invoke(context, parent, meta) as T? return visualFactories[T::class]?.invoke(context, parent, meta) as T?
} }
companion object : PluginFactory<VisualPlugin> { companion object : PluginFactory<Visual> {
override val tag: PluginTag = PluginTag(name = "visual", group = PluginTag.DATAFORGE_GROUP) override val tag: PluginTag = PluginTag(name = "visual", group = PluginTag.DATAFORGE_GROUP)
override val type: KClass<out VisualPlugin> = VisualPlugin::class override val type: KClass<out Visual> = Visual::class
override fun invoke(meta: Meta, context: Context): VisualPlugin = VisualPlugin(meta) override fun invoke(meta: Meta, context: Context): Visual = Visual(meta)
const val VISUAL_FACTORY_TYPE = "visual.factory" const val VISUAL_FACTORY_TYPE = "visual.factory"
} }

View File

@ -88,7 +88,7 @@ interface MutableVisualGroup : VisualGroup {
operator fun set(name: Name, child: VisualObject?) operator fun set(name: Name, child: VisualObject?)
} }
operator fun VisualGroup.get(str: String?) = get(str?.toName() ?: Name.EMPTY) operator fun VisualGroup.get(str: String?): VisualObject? = get(str?.toName() ?: Name.EMPTY)
operator fun MutableVisualGroup.set(key: String, child: VisualObject?) { operator fun MutableVisualGroup.set(key: String, child: VisualObject?) {
set(key.toName(), child) set(key.toName(), child)

View File

@ -7,7 +7,7 @@ kotlin {
val commonMain by getting { val commonMain by getting {
dependencies { dependencies {
api(project(":dataforge-vis-spatial")) api(project(":dataforge-vis-spatial"))
api("scientifik:gdml:0.1.5") api("scientifik:gdml:0.1.6")
} }
} }
} }

View File

@ -135,7 +135,7 @@ private fun jsonSchema(descriptor: SerialDescriptor, context: SerialModule): Jso
} }
fun main() { fun main() {
val context = Visual3DPlugin.serialModule val context = Visual3D.serialModule
val definitions = json { val definitions = json {
"children" to json { "children" to json {
"anyOf" to jsonArray { "anyOf" to jsonArray {

View File

@ -11,13 +11,14 @@ import hep.dataforge.vis.common.AbstractVisualObject
import hep.dataforge.vis.common.VisualFactory import hep.dataforge.vis.common.VisualFactory
import hep.dataforge.vis.common.VisualObject import hep.dataforge.vis.common.VisualObject
import hep.dataforge.vis.common.set import hep.dataforge.vis.common.set
import hep.dataforge.vis.spatial.Box.Companion.TYPE_NAME
import kotlinx.serialization.SerialName import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
import kotlinx.serialization.UseSerializers import kotlinx.serialization.UseSerializers
import kotlin.reflect.KClass import kotlin.reflect.KClass
@Serializable @Serializable
@SerialName("3d.box") @SerialName(TYPE_NAME)
class Box( class Box(
val xSize: Float, val xSize: Float,
val ySize: Float, val ySize: Float,
@ -53,7 +54,8 @@ class Box(
} }
companion object : VisualFactory<Box> { companion object : VisualFactory<Box> {
const val TYPE = "geometry.3d.box"
const val TYPE_NAME = "3d.box"
override val type: KClass<Box> get() = Box::class override val type: KClass<Box> get() = Box::class

View File

@ -59,7 +59,7 @@ class Proxy(val templateName: Name) : AbstractVisualObject(), VisualGroup, Visua
} }
override val children: Map<NameToken, ProxyChild> override val children: Map<NameToken, ProxyChild>
get() = (prototype as? MutableVisualGroup)?.children get() = (prototype as? VisualGroup)?.children
?.filter { !it.key.toString().startsWith("@") } ?.filter { !it.key.toString().startsWith("@") }
?.mapValues { ?.mapValues {
ProxyChild(it.key.asName()) ProxyChild(it.key.asName())
@ -85,7 +85,6 @@ class Proxy(val templateName: Name) : AbstractVisualObject(), VisualGroup, Visua
//override fun findAllStyles(): Laminate = Laminate((styles + prototype.styles).mapNotNull { findStyle(it) }) //override fun findAllStyles(): Laminate = Laminate((styles + prototype.styles).mapNotNull { findStyle(it) })
@Serializable
inner class ProxyChild(val name: Name) : AbstractVisualObject(), VisualGroup { inner class ProxyChild(val name: Name) : AbstractVisualObject(), VisualGroup {
val prototype: VisualObject get() = prototypeFor(name) val prototype: VisualObject get() = prototypeFor(name)

View File

@ -9,29 +9,32 @@ import hep.dataforge.io.serialization.MetaSerializer
import hep.dataforge.io.serialization.NameSerializer import hep.dataforge.io.serialization.NameSerializer
import hep.dataforge.meta.* import hep.dataforge.meta.*
import hep.dataforge.names.Name import hep.dataforge.names.Name
import hep.dataforge.names.toName
import hep.dataforge.vis.common.Visual
import hep.dataforge.vis.common.VisualObject import hep.dataforge.vis.common.VisualObject
import hep.dataforge.vis.common.VisualPlugin
import kotlinx.serialization.json.Json import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonConfiguration import kotlinx.serialization.json.JsonConfiguration
import kotlinx.serialization.modules.SerializersModule import kotlinx.serialization.modules.SerializersModule
import kotlinx.serialization.modules.contextual import kotlinx.serialization.modules.contextual
import kotlin.reflect.KClass import kotlin.reflect.KClass
class Visual3DPlugin(meta: Meta) : AbstractPlugin(meta) { class Visual3D(meta: Meta) : AbstractPlugin(meta) {
val visual by require(Visual)
override val tag: PluginTag get() = Companion.tag override val tag: PluginTag get() = Companion.tag
override fun provideTop(target: String): Map<Name, Any> { override fun provideTop(target: String): Map<Name, Any> = if (target == Visual.VISUAL_FACTORY_TYPE) {
return if (target == VisualPlugin.VISUAL_FACTORY_TYPE) { mapOf(Box.TYPE_NAME.toName() to Box)
mapOf()
} else { } else {
emptyMap() super.provideTop(target)
}
} }
companion object : PluginFactory<Visual3DPlugin> {
companion object : PluginFactory<Visual3D> {
override val tag: PluginTag = PluginTag(name = "visual.spatial", group = PluginTag.DATAFORGE_GROUP) override val tag: PluginTag = PluginTag(name = "visual.spatial", group = PluginTag.DATAFORGE_GROUP)
override val type: KClass<out Visual3DPlugin> = Visual3DPlugin::class override val type: KClass<out Visual3D> = Visual3D::class
override fun invoke(meta: Meta, context: Context): Visual3DPlugin = Visual3DPlugin(meta) override fun invoke(meta: Meta, context: Context): Visual3D = Visual3D(meta)
val serialModule = SerializersModule { val serialModule = SerializersModule {
contextual(Point3DSerializer) contextual(Point3DSerializer)

View File

@ -112,7 +112,7 @@ class VisualGroup3D : AbstractVisualGroup(), VisualObject3D {
// val PROTOTYPES_KEY = NameToken("@prototypes") // val PROTOTYPES_KEY = NameToken("@prototypes")
fun fromJson(json: String): VisualGroup3D = fun fromJson(json: String): VisualGroup3D =
Visual3DPlugin.json.parse(serializer(), json).also { it.attachChildren() } Visual3D.json.parse(serializer(), json).also { it.attachChildren() }
} }
} }

View File

@ -25,7 +25,7 @@ class ConvexTest {
val convex = group.first() as Convex val convex = group.first() as Convex
val json = Visual3DPlugin.json.toJson(Convex.serializer(), convex) val json = Visual3D.json.toJson(Convex.serializer(), convex)
val meta = json.toMeta() val meta = json.toMeta()
val points = meta.getIndexed("points").values.map { (it as MetaItem.NodeItem<*>).node.point3D()} val points = meta.getIndexed("points").values.map { (it as MetaItem.NodeItem<*>).node.point3D()}

View File

@ -1,6 +1,6 @@
package hep.dataforge.vis.spatial package hep.dataforge.vis.spatial
import hep.dataforge.vis.spatial.Visual3DPlugin.Companion.json import hep.dataforge.vis.spatial.Visual3D.Companion.json
import kotlinx.serialization.ImplicitReflectionSerializer import kotlinx.serialization.ImplicitReflectionSerializer
import kotlin.test.Test import kotlin.test.Test
import kotlin.test.assertEquals import kotlin.test.assertEquals

View File

@ -31,13 +31,15 @@ interface ThreeFactory<in T : VisualObject> {
/** /**
* Update position, rotation and visibility * Update position, rotation and visibility
*/ */
fun Object3D.updatePosition(obj: VisualObject3D) { fun Object3D.updatePosition(obj: VisualObject) {
visible = obj.visible ?: true visible = obj.visible ?: true
if(obj is VisualObject3D) {
position.set(obj.x, obj.y, obj.z) position.set(obj.x, obj.y, obj.z)
setRotationFromEuler(obj.euler) setRotationFromEuler(obj.euler)
scale.set(obj.scaleX, obj.scaleY, obj.scaleZ) scale.set(obj.scaleX, obj.scaleY, obj.scaleZ)
updateMatrix() updateMatrix()
} }
}
///** ///**
// * Unsafe invocation of a factory // * Unsafe invocation of a factory
@ -54,7 +56,7 @@ fun Object3D.updatePosition(obj: VisualObject3D) {
/** /**
* Update non-position non-geometry property * Update non-position non-geometry property
*/ */
fun Object3D.updateProperty(source: VisualObject3D, propertyName: Name) { fun Object3D.updateProperty(source: VisualObject, propertyName: Name) {
if (this is Mesh && propertyName.startsWith(MATERIAL_KEY)) { if (this is Mesh && propertyName.startsWith(MATERIAL_KEY)) {
this.material = getMaterial(source) this.material = getMaterial(source)
} else if ( } else if (

View File

@ -3,8 +3,8 @@ package hep.dataforge.vis.spatial.three
import hep.dataforge.meta.* import hep.dataforge.meta.*
import hep.dataforge.values.ValueType import hep.dataforge.values.ValueType
import hep.dataforge.vis.common.Colors import hep.dataforge.vis.common.Colors
import hep.dataforge.vis.common.VisualObject
import hep.dataforge.vis.spatial.Material3D import hep.dataforge.vis.spatial.Material3D
import hep.dataforge.vis.spatial.VisualObject3D
import info.laht.threekt.materials.LineBasicMaterial import info.laht.threekt.materials.LineBasicMaterial
import info.laht.threekt.materials.Material import info.laht.threekt.materials.Material
import info.laht.threekt.materials.MeshBasicMaterial import info.laht.threekt.materials.MeshBasicMaterial
@ -37,7 +37,7 @@ object ThreeMaterials {
} }
} }
fun getMaterial(visualObject3D: VisualObject3D): Material { fun getMaterial(visualObject3D: VisualObject): Material {
val meta = visualObject3D.getProperty(Material3D.MATERIAL_KEY).node ?: return ThreeMaterials.DEFAULT val meta = visualObject3D.getProperty(Material3D.MATERIAL_KEY).node ?: return ThreeMaterials.DEFAULT
return if (meta[Material3D.SPECULAR_COLOR_KEY] != null) { return if (meta[Material3D.SPECULAR_COLOR_KEY] != null) {
MeshPhongMaterial().apply { MeshPhongMaterial().apply {

View File

@ -25,7 +25,7 @@ class ThreeProxyFactory(val three: ThreePlugin) : ThreeFactory<Proxy> {
if (name.first()?.body == PROXY_CHILD_PROPERTY_PREFIX) { if (name.first()?.body == PROXY_CHILD_PROPERTY_PREFIX) {
val childName = name.first()?.index?.toName() ?: error("Wrong syntax for proxy child property: '$name'") val childName = name.first()?.index?.toName() ?: error("Wrong syntax for proxy child property: '$name'")
val propertyName = name.cutFirst() val propertyName = name.cutFirst()
val proxyChild = obj[childName] as? VisualObject3D ?: error("Proxy child with name '$childName' not found or not a 3D object") val proxyChild = obj[childName] ?: error("Proxy child with name '$childName' not found")
val child = object3D.findChild(childName)?: error("Object child with name '$childName' not found") val child = object3D.findChild(childName)?: error("Object child with name '$childName' not found")
child.updateProperty(proxyChild, propertyName) child.updateProperty(proxyChild, propertyName)
} else { } else {

View File

@ -2,7 +2,7 @@ package hep.dataforge.vis.spatial.three
import hep.dataforge.js.requireJS import hep.dataforge.js.requireJS
import hep.dataforge.vis.js.editor.card import hep.dataforge.vis.js.editor.card
import hep.dataforge.vis.spatial.Visual3DPlugin import hep.dataforge.vis.spatial.Visual3D
import hep.dataforge.vis.spatial.VisualGroup3D import hep.dataforge.vis.spatial.VisualGroup3D
import kotlinx.html.InputType import kotlinx.html.InputType
import kotlinx.html.TagConsumer import kotlinx.html.TagConsumer
@ -46,7 +46,7 @@ fun Element.displayCanvasControls(canvas: ThreeCanvas, block: TagConsumer<HTMLEl
+"Export" +"Export"
onClickFunction = { onClickFunction = {
val json = (canvas.content as? VisualGroup3D)?.let { group -> val json = (canvas.content as? VisualGroup3D)?.let { group ->
Visual3DPlugin.json.stringify( Visual3D.json.stringify(
VisualGroup3D.serializer(), VisualGroup3D.serializer(),
group group
) )

View File

@ -0,0 +1,54 @@
package hep.dataforge.vis.spatial.gdml.demo
import scientifik.gdml.*
fun cubes(): GDML = GDML {
val center = define.position("center")
structure {
val air = ref<GDMLMaterial>("G4_AIR")
val tubeMaterial = ref<GDMLMaterial>("tube")
val boxMaterial = ref<GDMLMaterial>("box")
val segment = solids.tube("segment", 20, 5.0) {
rmin = 17
deltaphi = 60
aunit = DEG
}
val worldBox = solids.box("LargeBox", 200, 200, 200)
val smallBox = solids.box("smallBox", 30, 30, 30)
val segmentVolume = volume("segment", tubeMaterial, segment.ref()) {}
val circle = volume("composite", boxMaterial, smallBox.ref()) {
for (i in 0 until 6) {
physVolume(segmentVolume) {
name = "segment$i"
positionref = center.ref()
rotation {
z = 60 * i
unit = DEG
}
}
}
}
world = volume("world", air, worldBox.ref()) {
for (i in 0 until 3) {
for (j in 0 until 3) {
for (k in 0 until 3) {
physVolume(circle) {
name = "composite$i$j$k"
position {
x = (-50 + i * 50)
y = (-50 + j * 50)
z = (-50 + k * 50)
}
rotation {
x = i * 120
y = j * 120
z = 120 * k
}
}
}
}
}
}
}
}

View File

@ -0,0 +1,18 @@
package hep.dataforge.vis.spatial.gdml
import hep.dataforge.meta.string
import hep.dataforge.names.toName
import hep.dataforge.vis.spatial.Material3D
import hep.dataforge.vis.spatial.gdml.demo.cubes
import kotlin.test.Test
import kotlin.test.assertEquals
class GDMLVisualTest {
@Test
fun testPrototypeProperty() {
val gdml = cubes()
val visual = gdml.toVisual()
visual["composite000.segment0".toName()]?.setProperty(Material3D.MATERIAL_COLOR_KEY, "red")
assertEquals("red", visual["composite000.segment0".toName()]?.getProperty(Material3D.MATERIAL_COLOR_KEY).string)
}
}

View File

@ -4,7 +4,7 @@ import hep.dataforge.context.Global
import hep.dataforge.vis.fx.editor.VisualObjectEditorFragment import hep.dataforge.vis.fx.editor.VisualObjectEditorFragment
import hep.dataforge.vis.fx.editor.VisualObjectTreeFragment import hep.dataforge.vis.fx.editor.VisualObjectTreeFragment
import hep.dataforge.vis.spatial.Material3D import hep.dataforge.vis.spatial.Material3D
import hep.dataforge.vis.spatial.Visual3DPlugin import hep.dataforge.vis.spatial.Visual3D
import hep.dataforge.vis.spatial.VisualGroup3D import hep.dataforge.vis.spatial.VisualGroup3D
import hep.dataforge.vis.spatial.fx.FX3DPlugin import hep.dataforge.vis.spatial.fx.FX3DPlugin
import hep.dataforge.vis.spatial.fx.FXCanvas3D import hep.dataforge.vis.spatial.fx.FXCanvas3D
@ -34,11 +34,11 @@ class GDMLView : View() {
override val root: Parent = borderpane { override val root: Parent = borderpane {
top { top {
buttonbar { buttonbar {
button("Load GDML") { button("Load GDML/json") {
action { action {
val file = chooseFile("Select a GDML/json file", filters = fileNameFilter).firstOrNull() val file = chooseFile("Select a GDML/json file", filters = fileNameFilter).firstOrNull()
?: return@action ?: return@action
val visual: VisualGroup3D = Visual3DPlugin.readFile(file) val visual: VisualGroup3D = Visual3D.readFile(file)
canvas.render(visual) canvas.render(visual)
} }
} }

View File

@ -1,7 +1,7 @@
package hep.dataforge.vis.spatial.gdml.demo package hep.dataforge.vis.spatial.gdml.demo
import hep.dataforge.vis.spatial.Material3D import hep.dataforge.vis.spatial.Material3D
import hep.dataforge.vis.spatial.Visual3DPlugin import hep.dataforge.vis.spatial.Visual3D
import hep.dataforge.vis.spatial.VisualGroup3D import hep.dataforge.vis.spatial.VisualGroup3D
import hep.dataforge.vis.spatial.gdml.LUnit import hep.dataforge.vis.spatial.gdml.LUnit
import hep.dataforge.vis.spatial.gdml.readFile import hep.dataforge.vis.spatial.gdml.readFile
@ -11,7 +11,7 @@ import java.io.File
import java.util.zip.GZIPInputStream import java.util.zip.GZIPInputStream
import java.util.zip.ZipInputStream import java.util.zip.ZipInputStream
fun Visual3DPlugin.Companion.readFile(file: File): VisualGroup3D = when { fun Visual3D.Companion.readFile(file: File): VisualGroup3D = when {
file.extension == "gdml" || file.extension == "xml" -> { file.extension == "gdml" || file.extension == "xml" -> {
GDML.readFile(file.toPath()).toVisual { GDML.readFile(file.toPath()).toVisual {
lUnit = LUnit.CM lUnit = LUnit.CM
@ -46,4 +46,4 @@ fun Visual3DPlugin.Companion.readFile(file: File): VisualGroup3D = when {
else -> error("Unknown extension ${file.extension}") else -> error("Unknown extension ${file.extension}")
} }
fun Visual3DPlugin.Companion.readFile(fileName: String): VisualGroup3D = readFile(File(fileName)) fun Visual3D.Companion.readFile(fileName: String): VisualGroup3D = readFile(File(fileName))

View File

@ -1,6 +1,6 @@
package hep.dataforge.vis.spatial.gdml.demo package hep.dataforge.vis.spatial.gdml.demo
import hep.dataforge.vis.spatial.Visual3DPlugin import hep.dataforge.vis.spatial.Visual3D
import hep.dataforge.vis.spatial.VisualGroup3D import hep.dataforge.vis.spatial.VisualGroup3D
import hep.dataforge.vis.spatial.gdml.LUnit import hep.dataforge.vis.spatial.gdml.LUnit
import hep.dataforge.vis.spatial.gdml.readFile import hep.dataforge.vis.spatial.gdml.readFile
@ -14,6 +14,6 @@ fun main() {
val visual = gdml.toVisual { val visual = gdml.toVisual {
lUnit = LUnit.CM lUnit = LUnit.CM
} }
val json = Visual3DPlugin.json.stringify(VisualGroup3D.serializer(), visual) val json = Visual3D.json.stringify(VisualGroup3D.serializer(), visual)
File("D:\\Work\\Projects\\gdml.kt\\gdml-source\\cubes.json").writeText(json) File("D:\\Work\\Projects\\gdml.kt\\gdml-source\\cubes.json").writeText(json)
} }

View File

@ -15,7 +15,7 @@ import hep.dataforge.vis.js.editor.displayPropertyEditor
import hep.dataforge.vis.spatial.Material3D.Companion.MATERIAL_COLOR_KEY import hep.dataforge.vis.spatial.Material3D.Companion.MATERIAL_COLOR_KEY
import hep.dataforge.vis.spatial.Material3D.Companion.MATERIAL_OPACITY_KEY import hep.dataforge.vis.spatial.Material3D.Companion.MATERIAL_OPACITY_KEY
import hep.dataforge.vis.spatial.Material3D.Companion.MATERIAL_WIREFRAME_KEY import hep.dataforge.vis.spatial.Material3D.Companion.MATERIAL_WIREFRAME_KEY
import hep.dataforge.vis.spatial.Visual3DPlugin import hep.dataforge.vis.spatial.Visual3D
import hep.dataforge.vis.spatial.VisualObject3D import hep.dataforge.vis.spatial.VisualObject3D
import hep.dataforge.vis.spatial.VisualObject3D.Companion.VISIBLE_KEY import hep.dataforge.vis.spatial.VisualObject3D.Companion.VISIBLE_KEY
import hep.dataforge.vis.spatial.three.ThreePlugin import hep.dataforge.vis.spatial.three.ThreePlugin
@ -41,7 +41,7 @@ private class MMDemoApp : Application {
private val connection = HttpClient { private val connection = HttpClient {
install(JsonFeature) { install(JsonFeature) {
serializer = KotlinxSerializer(Visual3DPlugin.json) serializer = KotlinxSerializer(Visual3D.json)
} }
} }

View File

@ -1,7 +1,7 @@
package ru.mipt.npm.muon.monitor.server package ru.mipt.npm.muon.monitor.server
import hep.dataforge.vis.spatial.Visual3DPlugin import hep.dataforge.vis.spatial.Visual3D
import io.ktor.application.Application import io.ktor.application.Application
import io.ktor.application.call import io.ktor.application.call
import io.ktor.application.install import io.ktor.application.install
@ -35,7 +35,7 @@ fun Application.module() {
install(DefaultHeaders) install(DefaultHeaders)
install(CallLogging) install(CallLogging)
install(ContentNegotiation) { install(ContentNegotiation) {
serialization(json = Visual3DPlugin.json) serialization(json = Visual3D.json)
} }
install(Routing) { install(Routing) {
get("/event") { get("/event") {