Style cleanup

Fix rotation order
This commit is contained in:
Alexander Nozik 2019-12-23 15:53:47 +03:00
parent 8189012b70
commit a5a03f1c02
11 changed files with 126 additions and 70 deletions

View File

@ -3,8 +3,7 @@
package hep.dataforge.vis.common package hep.dataforge.vis.common
import hep.dataforge.io.serialization.MetaSerializer import hep.dataforge.io.serialization.MetaSerializer
import hep.dataforge.meta.Meta import hep.dataforge.meta.*
import hep.dataforge.meta.get
import hep.dataforge.names.Name import hep.dataforge.names.Name
import hep.dataforge.names.asName import hep.dataforge.names.asName
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
@ -37,6 +36,15 @@ class StyleSheet() {
} }
owner?.styleChanged(key, oldStyle, style) owner?.styleChanged(key, oldStyle, style)
} }
infix fun String.put(style: Meta?) {
set(this, style)
}
operator fun set(key: String, builder: MetaBuilder.() -> Unit) {
val newStyle = get(key)?.let { buildMeta(it, builder) } ?: buildMeta(builder)
set(key, newStyle.seal())
}
} }
private fun VisualObject.styleChanged(key: String, oldStyle: Meta?, newStyle: Meta?) { private fun VisualObject.styleChanged(key: String, oldStyle: Meta?, newStyle: Meta?) {

View File

@ -1,8 +1,5 @@
package hep.dataforge.vis.common package hep.dataforge.vis.common
import hep.dataforge.meta.MetaBuilder
import hep.dataforge.meta.buildMeta
import hep.dataforge.meta.seal
import hep.dataforge.names.* import hep.dataforge.names.*
import hep.dataforge.provider.Provider import hep.dataforge.provider.Provider
@ -14,7 +11,7 @@ interface VisualGroup : Provider, Iterable<VisualObject>, VisualObject {
override val defaultTarget: String get() = VisualObject.TYPE override val defaultTarget: String get() = VisualObject.TYPE
val styleSheet: StyleSheet val styleSheet: StyleSheet?
override fun provideTop(target: String): Map<Name, Any> = override fun provideTop(target: String): Map<Name, Any> =
when (target) { when (target) {
@ -26,7 +23,7 @@ interface VisualGroup : Provider, Iterable<VisualObject>, VisualObject {
} }
res.entries res.entries
}.associate { it.toPair() } }.associate { it.toPair() }
STYLE_TARGET -> styleSheet.items.mapKeys { it.key.toName() } STYLE_TARGET -> styleSheet?.items?.mapKeys { it.key.toName() } ?: emptyMap()
else -> emptyMap() else -> emptyMap()
} }
@ -47,8 +44,8 @@ interface VisualGroup : Provider, Iterable<VisualObject>, VisualObject {
/** /**
* A fix for serialization bug that writes all proper parents inside the tree after deserialization * A fix for serialization bug that writes all proper parents inside the tree after deserialization
*/ */
fun attachChildren(){ fun attachChildren() {
styleSheet.owner = this styleSheet?.owner = this
this.children.values.forEach { this.children.values.forEach {
it.parent = this it.parent = this
(it as? VisualGroup)?.attachChildren() (it as? VisualGroup)?.attachChildren()
@ -60,11 +57,6 @@ interface VisualGroup : Provider, Iterable<VisualObject>, VisualObject {
} }
} }
fun VisualGroup.updateStyle(key: String, builder: MetaBuilder.() -> Unit) {
val newStyle = styleSheet[key]?.let { buildMeta(it, builder) } ?: buildMeta(builder)
styleSheet[key] = newStyle.seal()
}
data class StyleRef(val group: VisualGroup, val styleName: Name) data class StyleRef(val group: VisualGroup, val styleName: Name)
val VisualGroup.isEmpty: Boolean get() = this.children.isEmpty() val VisualGroup.isEmpty: Boolean get() = this.children.isEmpty()

View File

@ -40,7 +40,7 @@ class GDMLTransformer(val root: GDML) {
var solidConfiguration: VisualObject3D.(parent: GDMLVolume, solid: GDMLSolid) -> Unit = { _, _ -> } var solidConfiguration: VisualObject3D.(parent: GDMLVolume, solid: GDMLSolid) -> Unit = { _, _ -> }
fun VisualObject.useStyle(name: String, builder: MetaBuilder.() -> Unit) { fun VisualObject.useStyle(name: String, builder: MetaBuilder.() -> Unit) {
styleCache.getOrPut(name.toName()){ styleCache.getOrPut(name.toName()) {
buildMeta(builder) buildMeta(builder)
} }
useStyle(name) useStyle(name)
@ -51,7 +51,7 @@ class GDMLTransformer(val root: GDML) {
val styleName = "material[${material.name}]" val styleName = "material[${material.name}]"
obj.useStyle(styleName){ obj.useStyle(styleName) {
MATERIAL_COLOR_KEY put random.nextInt(16777216) MATERIAL_COLOR_KEY put random.nextInt(16777216)
"gdml.material" put material.name "gdml.material" put material.name
} }
@ -68,7 +68,9 @@ class GDMLTransformer(val root: GDML) {
internal fun finalize(final: VisualGroup3D): VisualGroup3D { internal fun finalize(final: VisualGroup3D): VisualGroup3D {
final.prototypes = proto final.prototypes = proto
styleCache.forEach { styleCache.forEach {
final.styleSheet[it.key.toString()] = it.value final.styleSheet {
this[it.key.toString()] = it.value
}
} }
final.rotationOrder = RotationOrder.ZXY final.rotationOrder = RotationOrder.ZXY
onFinish(this@GDMLTransformer) onFinish(this@GDMLTransformer)

View File

@ -250,5 +250,7 @@ fun GDML.toVisual(block: GDMLTransformer.() -> Unit = {}): VisualGroup3D {
* Append gdml node to the group * Append gdml node to the group
*/ */
fun VisualGroup3D.gdml(gdml: GDML, key: String = "", transformer: GDMLTransformer.() -> Unit = {}) { fun VisualGroup3D.gdml(gdml: GDML, key: String = "", transformer: GDMLTransformer.() -> Unit = {}) {
set(key, gdml.toVisual(transformer)) val visual = gdml.toVisual(transformer)
println(Visual3DPlugin.json.stringify(VisualGroup3D.serializer(),visual))
set(key, visual)
} }

View File

@ -47,9 +47,15 @@ inline fun VisualGroup3D.composite(
it.config.update(group.config) it.config.update(group.config)
//it.material = group.material //it.material = group.material
it.position = group.position if(group.position!=null) {
it.rotation = group.rotation it.position = group.position
it.scale = group.scale }
if(group.rotation!=null) {
it.rotation = group.rotation
}
if(group.scale!=null) {
it.scale = group.scale
}
set(name, it) set(name, it)
} }
} }

View File

@ -46,8 +46,8 @@ class Proxy(val templateName: Name) : AbstractVisualObject(), VisualGroup, Visua
return if (inherit) { return if (inherit) {
properties?.get(name) properties?.get(name)
?: mergedStyles[name] ?: mergedStyles[name]
?: prototype.getProperty(name, false) ?: prototype.getProperty(name)
?: parent?.getProperty(name, inherit) ?: parent?.getProperty(name)
} else { } else {
properties?.get(name) properties?.get(name)
?: mergedStyles[name] ?: mergedStyles[name]
@ -74,7 +74,6 @@ class Proxy(val templateName: Name) : AbstractVisualObject(), VisualGroup, Visua
?: error("Prototype with name $name not found in $this") ?: error("Prototype with name $name not found in $this")
} }
override var styles: List<String> override var styles: List<String>
get() = super.styles + prototype.styles get() = super.styles + prototype.styles
set(value) { set(value) {
@ -119,12 +118,12 @@ class Proxy(val templateName: Name) : AbstractVisualObject(), VisualGroup, Visua
return if (inherit) { return if (inherit) {
properties?.get(name) properties?.get(name)
?: mergedStyles[name] ?: mergedStyles[name]
?: prototype.getProperty(name, inherit) ?: prototype.getProperty(name)
?: parent?.getProperty(name, inherit) ?: parent?.getProperty(name)
} else { } else {
properties?.get(name) properties?.get(name)
?: mergedStyles[name] ?: mergedStyles[name]
?: prototype.getProperty(name, inherit) ?: prototype.getProperty(name, false)
} }
} }
@ -135,11 +134,11 @@ class Proxy(val templateName: Name) : AbstractVisualObject(), VisualGroup, Visua
} }
} }
val VisualObject.prototype: VisualObject? val VisualObject.prototype: VisualObject
get() = when (this) { get() = when (this) {
is Proxy -> prototype is Proxy -> prototype
is Proxy.ProxyChild -> prototype is Proxy.ProxyChild -> prototype
else -> null else -> this
} }
/** /**
@ -158,12 +157,11 @@ fun VisualGroup3D.proxy(
templateName: Name, templateName: Name,
obj: VisualObject3D, obj: VisualObject3D,
name: String = "", name: String = "",
attachToParent: Boolean = false,
block: Proxy.() -> Unit = {} block: Proxy.() -> Unit = {}
): Proxy { ): Proxy {
val existing = getPrototype(templateName) val existing = getPrototype(templateName)
if (existing == null) { if (existing == null) {
setPrototype(templateName, obj, attachToParent) setPrototype(templateName, obj)
} else if (existing != obj) { } else if (existing != obj) {
error("Can't add different prototype on top of existing one") error("Can't add different prototype on top of existing one")
} }

View File

@ -18,7 +18,6 @@ import hep.dataforge.names.asName
import hep.dataforge.names.isEmpty import hep.dataforge.names.isEmpty
import hep.dataforge.vis.common.AbstractVisualGroup import hep.dataforge.vis.common.AbstractVisualGroup
import hep.dataforge.vis.common.StyleSheet import hep.dataforge.vis.common.StyleSheet
import hep.dataforge.vis.common.VisualGroup
import hep.dataforge.vis.common.VisualObject import hep.dataforge.vis.common.VisualObject
import kotlinx.serialization.SerialName import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
@ -37,7 +36,8 @@ class VisualGroup3D : AbstractVisualGroup(), VisualObject3D {
field = value field = value
} }
override val styleSheet: StyleSheet = StyleSheet(this) override var styleSheet: StyleSheet? = null
private set
//FIXME to be lifted to AbstractVisualGroup after https://github.com/Kotlin/kotlinx.serialization/issues/378 is fixed //FIXME to be lifted to AbstractVisualGroup after https://github.com/Kotlin/kotlinx.serialization/issues/378 is fixed
override var properties: Config? = null override var properties: Config? = null
@ -55,6 +55,14 @@ class VisualGroup3D : AbstractVisualGroup(), VisualObject3D {
attachChildren() attachChildren()
} }
/**
* Update or create stylesheet
*/
fun styleSheet(block: StyleSheet.() -> Unit) {
val res = this.styleSheet ?: StyleSheet(this).also { this.styleSheet = it }
res.block()
}
override fun removeChild(token: NameToken) { override fun removeChild(token: NameToken) {
_children.remove(token) _children.remove(token)
childrenChanged(token.asName(), null) childrenChanged(token.asName(), null)
@ -90,18 +98,6 @@ class VisualGroup3D : AbstractVisualGroup(), VisualObject3D {
} }
} }
fun getPrototype(name: Name): VisualObject3D? =
prototypes?.get(name) as? VisualObject3D ?: (parent as? VisualGroup3D)?.getPrototype(name)
fun setPrototype(name: Name, obj: VisualObject3D, attachToParent: Boolean = false) {
val parent = this.parent
if (attachToParent && parent is VisualGroup3D) {
parent.setPrototype(name, obj, attachToParent)
} else {
(prototypes ?: VisualGroup3D().also { this.prototypes = it }).set(name, obj)
}
}
override fun attachChildren() { override fun attachChildren() {
super.attachChildren() super.attachChildren()
prototypes?.run { prototypes?.run {
@ -115,5 +111,28 @@ class VisualGroup3D : AbstractVisualGroup(), VisualObject3D {
} }
} }
/**
* Ger a prototype redirecting the request to the parent if prototype is not found
*/
fun VisualGroup3D.getPrototype(name: Name): VisualObject3D? =
prototypes?.get(name) as? VisualObject3D ?: (parent as? VisualGroup3D)?.getPrototype(name)
/**
* Defined a prototype inside current group
*/
fun VisualGroup3D.setPrototype(name: Name, obj: VisualObject3D) {
(prototypes ?: VisualGroup3D().also { this.prototypes = it })[name] = obj
}
/**
* Define a group with given [key], attach it to this parent and return it.
*/
fun VisualGroup3D.group(key: String = "", action: VisualGroup3D.() -> Unit = {}): VisualGroup3D = fun VisualGroup3D.group(key: String = "", action: VisualGroup3D.() -> Unit = {}): VisualGroup3D =
VisualGroup3D().apply(action).also { set(key, it) } VisualGroup3D().apply(action).also { set(key, it) }
/**
* Create or edit prototype node as a group
*/
inline fun VisualGroup3D.prototypes(builder: VisualGroup3D.() -> Unit): Unit {
(prototypes ?: VisualGroup3D().also { this.prototypes = it }).run(builder)
}

View File

@ -3,33 +3,34 @@ package hep.dataforge.vis.spatial
import hep.dataforge.meta.int import hep.dataforge.meta.int
import hep.dataforge.meta.set import hep.dataforge.meta.set
import hep.dataforge.names.asName import hep.dataforge.names.asName
import hep.dataforge.vis.common.updateStyle
import hep.dataforge.vis.common.useStyle import hep.dataforge.vis.common.useStyle
import kotlin.test.Test import kotlin.test.Test
import kotlin.test.assertEquals import kotlin.test.assertEquals
class PropertyTest { class PropertyTest {
@Test @Test
fun testInheritedProperty(){ fun testInheritedProperty() {
var box: Box? = null var box: Box? = null
val group = VisualGroup3D().apply { val group = VisualGroup3D().apply {
config["test"] = 22 config["test"] = 22
group { group {
box = box(100,100,100) box = box(100, 100, 100)
} }
} }
assertEquals(22, box?.getProperty("test".asName()).int) assertEquals(22, box?.getProperty("test".asName()).int)
} }
@Test @Test
fun testStyleProperty(){ fun testStyleProperty() {
var box: Box? = null var box: Box? = null
val group = VisualGroup3D().apply { val group = VisualGroup3D().apply {
updateStyle("testStyle"){ styleSheet {
"test" put 22 set("testStyle") {
"test" put 22
}
} }
group { group {
box = box(100,100,100).apply { box = box(100, 100, 100).apply {
useStyle("testStyle") useStyle("testStyle")
} }
} }
@ -38,18 +39,41 @@ class PropertyTest {
} }
@Test @Test
fun testColor(){ fun testColor() {
var box: Box? = null var box: Box? = null
val group = VisualGroup3D().apply { val group = VisualGroup3D().apply {
updateStyle("testStyle"){ styleSheet {
Material3D.MATERIAL_COLOR_KEY put "#555555" set("testStyle") {
Material3D.MATERIAL_COLOR_KEY put "#555555"
}
} }
group { group {
box = box(100,100,100){ box = box(100, 100, 100) {
useStyle("testStyle") useStyle("testStyle")
} }
} }
} }
assertEquals("#555555", box?.color) assertEquals("#555555", box?.color)
} }
@Test
fun testProxyStyleProperty() {
var box: Proxy? = null
val group = VisualGroup3D().apply {
styleSheet {
set("testStyle") {
Material3D.MATERIAL_COLOR_KEY put "#555555"
}
}
prototypes {
box(100, 100, 100, name = "box") {
styles = listOf("testStyle")
}
}
group {
box = ref("box".asName())
}
}
assertEquals("#555555", box?.color)
}
} }

View File

@ -2,7 +2,10 @@ package hep.dataforge.vis.spatial.editor
import hep.dataforge.io.toJson import hep.dataforge.io.toJson
import hep.dataforge.js.jsObject import hep.dataforge.js.jsObject
import hep.dataforge.meta.* import hep.dataforge.meta.DynamicMeta
import hep.dataforge.meta.Meta
import hep.dataforge.meta.builder
import hep.dataforge.meta.update
import hep.dataforge.vis.common.VisualObject import hep.dataforge.vis.common.VisualObject
import hep.dataforge.vis.common.findStyle import hep.dataforge.vis.common.findStyle
import hep.dataforge.vis.spatial.* import hep.dataforge.vis.spatial.*
@ -24,11 +27,7 @@ fun Element.propertyEditor(item: VisualObject?) {
if (item != null) { if (item != null) {
append { append {
card("Properties") { card("Properties") {
val config: Meta = if (item is Proxy || item is Proxy.ProxyChild) { val config: Meta = item.prototype.config
item.prototype?.config ?: EmptyMeta
} else {
item.config
}
val metaToEdit = config.builder().apply { val metaToEdit = config.builder().apply {
VISIBLE_KEY to (item.visible ?: true) VISIBLE_KEY to (item.visible ?: true)
if (item is VisualObject3D) { if (item is VisualObject3D) {

View File

@ -3,7 +3,6 @@ package hep.dataforge.vis.spatial.fx
import hep.dataforge.context.* import hep.dataforge.context.*
import hep.dataforge.meta.Meta import hep.dataforge.meta.Meta
import hep.dataforge.meta.boolean import hep.dataforge.meta.boolean
import hep.dataforge.meta.get
import hep.dataforge.provider.Type import hep.dataforge.provider.Type
import hep.dataforge.vis.spatial.* import hep.dataforge.vis.spatial.*
import hep.dataforge.vis.spatial.Material3D.Companion.MATERIAL_KEY import hep.dataforge.vis.spatial.Material3D.Companion.MATERIAL_KEY
@ -20,6 +19,13 @@ import javafx.scene.transform.Rotate
import org.fxyz3d.shapes.composites.PolyLine3D import org.fxyz3d.shapes.composites.PolyLine3D
import org.fxyz3d.shapes.primitives.CuboidMesh import org.fxyz3d.shapes.primitives.CuboidMesh
import org.fxyz3d.shapes.primitives.SpheroidMesh import org.fxyz3d.shapes.primitives.SpheroidMesh
import kotlin.collections.HashMap
import kotlin.collections.component1
import kotlin.collections.component2
import kotlin.collections.find
import kotlin.collections.map
import kotlin.collections.mapNotNull
import kotlin.collections.set
import kotlin.math.PI import kotlin.math.PI
import kotlin.reflect.KClass import kotlin.reflect.KClass
@ -106,11 +112,11 @@ class FX3DPlugin : AbstractPlugin() {
when (obj.rotationOrder) { when (obj.rotationOrder) {
RotationOrder.ZYX -> transforms.addAll(rotateZ, rotateY, rotateX) RotationOrder.ZYX -> transforms.addAll(rotateZ, rotateY, rotateX)
RotationOrder.XZY -> transforms.addAll(rotateY, rotateZ, rotateX) RotationOrder.XZY -> transforms.addAll(rotateX, rotateZ, rotateY)
RotationOrder.YXZ -> transforms.addAll(rotateZ, rotateX, rotateY) RotationOrder.YXZ -> transforms.addAll(rotateY, rotateX, rotateZ)
RotationOrder.YZX -> transforms.addAll(rotateX, rotateZ, rotateY) RotationOrder.YZX -> transforms.addAll(rotateY, rotateZ, rotateX)
RotationOrder.ZXY -> transforms.addAll(rotateY, rotateX, rotateZ) RotationOrder.ZXY -> transforms.addAll(rotateZ, rotateX, rotateY)
RotationOrder.XYZ -> transforms.addAll(rotateZ, rotateY, rotateX) RotationOrder.XYZ -> transforms.addAll(rotateX, rotateY, rotateZ)
} }
if (this is Shape3D) { if (this is Shape3D) {

View File

@ -17,7 +17,7 @@ class FXDemoApp : App(FXDemoGrid::class) {
stage.width = 400.0 stage.width = 400.0
stage.height = 400.0 stage.height = 400.0
//view.showcase() view.showcase()
view.demo("gdml", "gdml") { view.demo("gdml", "gdml") {
gdml(Paths.get("D:\\Work\\Projects\\gdml.kt\\gdml-source\\cubes.gdml")) { gdml(Paths.get("D:\\Work\\Projects\\gdml.kt\\gdml-source\\cubes.gdml")) {
lUnit = LUnit.CM lUnit = LUnit.CM