forked from kscience/visionforge
Updated plugin and GDML conversion optimization
This commit is contained in:
parent
dffc1e039b
commit
e5a27ab56f
@ -1,17 +1,15 @@
|
|||||||
val dataforgeVersion by extra("0.1.3")
|
val dataforgeVersion by extra("0.1.3")
|
||||||
|
|
||||||
plugins{
|
plugins{
|
||||||
val kotlinVersion = "1.3.50-eap-5"
|
val kotlinVersion = "1.3.50"
|
||||||
|
|
||||||
kotlin("jvm") version kotlinVersion apply false
|
kotlin("jvm") version kotlinVersion apply false
|
||||||
id("kotlin2js") version kotlinVersion apply false
|
|
||||||
id("kotlin-dce-js") version kotlinVersion apply false
|
id("kotlin-dce-js") version kotlinVersion apply false
|
||||||
id("org.jetbrains.kotlin.frontend") version "0.0.45" apply false
|
id("scientifik.mpp") version "0.1.7" apply false
|
||||||
id("scientifik.mpp") version "0.1.4" apply false
|
id("scientifik.jvm") version "0.1.7" apply false
|
||||||
id("scientifik.jvm") version "0.1.4" apply false
|
id("scientifik.js") version "0.1.7" apply false
|
||||||
id("scientifik.js") version "0.1.4" apply false
|
id("scientifik.publish") version "0.1.7" apply false
|
||||||
id("scientifik.publish") version "0.1.4" apply false
|
id("org.openjfx.javafxplugin") version "0.0.8" apply false
|
||||||
id("org.openjfx.javafxplugin") version "0.0.7" apply false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
allprojects {
|
allprojects {
|
||||||
@ -19,7 +17,6 @@ allprojects {
|
|||||||
mavenLocal()
|
mavenLocal()
|
||||||
jcenter()
|
jcenter()
|
||||||
maven("https://kotlin.bintray.com/kotlinx")
|
maven("https://kotlin.bintray.com/kotlinx")
|
||||||
maven("http://npm.mipt.ru:8081/artifactory/gradle-dev-local")
|
|
||||||
maven("https://kotlin.bintray.com/js-externals")
|
maven("https://kotlin.bintray.com/js-externals")
|
||||||
maven("https://dl.bintray.com/pdvrieze/maven")
|
maven("https://dl.bintray.com/pdvrieze/maven")
|
||||||
maven("https://dl.bintray.com/kotlin/kotlin-eap")
|
maven("https://dl.bintray.com/kotlin/kotlin-eap")
|
||||||
|
@ -3,7 +3,7 @@ plugins {
|
|||||||
}
|
}
|
||||||
|
|
||||||
scientifik{
|
scientifik{
|
||||||
serialization = true
|
withSerialization()
|
||||||
}
|
}
|
||||||
|
|
||||||
val dataforgeVersion: String by rootProject.extra
|
val dataforgeVersion: String by rootProject.extra
|
||||||
|
@ -108,7 +108,7 @@ abstract class AbstractVisualGroup : AbstractVisualObject(), VisualGroup {
|
|||||||
set(key.asName(), child)
|
set(key.asName(), child)
|
||||||
}
|
}
|
||||||
|
|
||||||
operator fun set(key: String?, child: VisualObject?) = set(key ?: "", child)
|
// operator fun set(key: String?, child: VisualObject?) = set(key ?: "", child)
|
||||||
|
|
||||||
protected fun MetaBuilder.updateChildren() {
|
protected fun MetaBuilder.updateChildren() {
|
||||||
//adding named children
|
//adding named children
|
||||||
|
@ -2,12 +2,16 @@ plugins {
|
|||||||
id("scientifik.mpp")
|
id("scientifik.mpp")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
scientifik{
|
||||||
|
withSerialization()
|
||||||
|
}
|
||||||
|
|
||||||
kotlin {
|
kotlin {
|
||||||
sourceSets {
|
sourceSets {
|
||||||
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.4-dev-1")
|
api("scientifik:gdml:0.1.4-dev-3")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
val jsMain by getting {
|
val jsMain by getting {
|
||||||
|
@ -64,9 +64,18 @@ class GDMLTransformer(val root: GDML) {
|
|||||||
|
|
||||||
var onFinish: GDMLTransformer.() -> Unit = {}
|
var onFinish: GDMLTransformer.() -> Unit = {}
|
||||||
|
|
||||||
internal fun finished(final: VisualGroup3D) {
|
var optimizeSingleChild = false
|
||||||
|
|
||||||
|
//var optimizations: List<GDMLOptimization> = emptyList()
|
||||||
|
|
||||||
|
internal fun finalize(final: VisualGroup3D): VisualGroup3D {
|
||||||
|
// var res = final
|
||||||
|
// optimizations.forEach {
|
||||||
|
// res = it(res)
|
||||||
|
// }
|
||||||
final.templates = templates
|
final.templates = templates
|
||||||
onFinish(this@GDMLTransformer)
|
onFinish(this@GDMLTransformer)
|
||||||
|
return final
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -0,0 +1,58 @@
|
|||||||
|
package hep.dataforge.vis.spatial.gdml
|
||||||
|
|
||||||
|
import hep.dataforge.meta.update
|
||||||
|
import hep.dataforge.names.asName
|
||||||
|
import hep.dataforge.vis.common.VisualGroup
|
||||||
|
import hep.dataforge.vis.spatial.Point3D
|
||||||
|
import hep.dataforge.vis.spatial.VisualGroup3D
|
||||||
|
import hep.dataforge.vis.spatial.VisualObject3D
|
||||||
|
import hep.dataforge.vis.spatial.plus
|
||||||
|
import kotlin.collections.component1
|
||||||
|
import kotlin.collections.component2
|
||||||
|
|
||||||
|
typealias GDMLOptimization = GDMLTransformer.(VisualGroup3D) -> VisualGroup3D
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Collapse nodes with single child
|
||||||
|
*/
|
||||||
|
val optimizeSingleChild: GDMLOptimization = { tree ->
|
||||||
|
fun VisualGroup.replaceChildren() {
|
||||||
|
children.forEach { (key, child) ->
|
||||||
|
if (child is VisualGroup3D && child.children.size == 1) {
|
||||||
|
val newChild = child.children.values.first().apply {
|
||||||
|
config.update(child.config)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newChild is VisualObject3D) {
|
||||||
|
newChild.apply {
|
||||||
|
position += child.position
|
||||||
|
rotation += child.rotation
|
||||||
|
scale = when {
|
||||||
|
scale == null && child.scale == null -> null
|
||||||
|
scale == null -> child.scale
|
||||||
|
child.scale == null -> scale
|
||||||
|
else -> Point3D(
|
||||||
|
scale!!.x * child.scale!!.x,
|
||||||
|
scale!!.y * child.scale!!.y,
|
||||||
|
scale!!.z * child.scale!!.z
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newChild is VisualGroup) {
|
||||||
|
newChild.replaceChildren()
|
||||||
|
}
|
||||||
|
|
||||||
|
//actual replacement
|
||||||
|
set(key.asName(), newChild)
|
||||||
|
} else if (child is VisualGroup) {
|
||||||
|
child.replaceChildren()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tree.replaceChildren()
|
||||||
|
|
||||||
|
tree
|
||||||
|
}
|
@ -149,7 +149,25 @@ private fun VisualGroup3D.addPhysicalVolume(
|
|||||||
|
|
||||||
when (context.volumeAction(volume)) {
|
when (context.volumeAction(volume)) {
|
||||||
GDMLTransformer.Action.ACCEPT -> {
|
GDMLTransformer.Action.ACCEPT -> {
|
||||||
this[physVolume.name] = volume(context, volume).apply {
|
val group = volume(context, volume)
|
||||||
|
//optimizing single child case
|
||||||
|
if (context.optimizeSingleChild && group.children.size == 1) {
|
||||||
|
this[physVolume.name ?: "@unnamed"] = group.children.values.first().apply {
|
||||||
|
//Must ser this to avoid parent reset error
|
||||||
|
parent = null
|
||||||
|
//setting offset from physical volume
|
||||||
|
withPosition(
|
||||||
|
context.lUnit,
|
||||||
|
physVolume.resolvePosition(context.root),
|
||||||
|
physVolume.resolveRotation(context.root),
|
||||||
|
physVolume.resolveScale(context.root)
|
||||||
|
)
|
||||||
|
// in case when both phys volume and underlying volume have offset
|
||||||
|
position += group.position
|
||||||
|
rotation += group.rotation
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this[physVolume.name ?: "@unnamed"] = group.apply {
|
||||||
withPosition(
|
withPosition(
|
||||||
context.lUnit,
|
context.lUnit,
|
||||||
physVolume.resolvePosition(context.root),
|
physVolume.resolvePosition(context.root),
|
||||||
@ -158,13 +176,14 @@ private fun VisualGroup3D.addPhysicalVolume(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
GDMLTransformer.Action.CACHE -> {
|
GDMLTransformer.Action.CACHE -> {
|
||||||
val name = volumesName + volume.name.asName()
|
val name = volumesName + volume.name.asName()
|
||||||
if (context.templates[name] == null) {
|
if (context.templates[name] == null) {
|
||||||
context.templates[name] = volume(context, volume)
|
context.templates[name] = volume(context, volume)
|
||||||
}
|
}
|
||||||
|
|
||||||
this[physVolume.name] = Proxy(name).apply {
|
this[physVolume.name ?: ""] = Proxy(name).apply {
|
||||||
withPosition(
|
withPosition(
|
||||||
context.lUnit,
|
context.lUnit,
|
||||||
physVolume.resolvePosition(context.root),
|
physVolume.resolvePosition(context.root),
|
||||||
@ -196,12 +215,12 @@ private fun VisualGroup3D.addDivisionVolume(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun VisualGroup3D.addVolume(
|
//private fun VisualGroup3D.addVolume(
|
||||||
context: GDMLTransformer,
|
// context: GDMLTransformer,
|
||||||
group: GDMLGroup
|
// group: GDMLGroup
|
||||||
) {
|
//) {
|
||||||
this[group.name] = volume(context, group)
|
// this[group.name] = volume(context, group)
|
||||||
}
|
//}
|
||||||
|
|
||||||
private fun volume(
|
private fun volume(
|
||||||
context: GDMLTransformer,
|
context: GDMLTransformer,
|
||||||
@ -211,7 +230,6 @@ private fun volume(
|
|||||||
if (group is GDMLVolume) {
|
if (group is GDMLVolume) {
|
||||||
val solid = group.solidref.resolve(context.root)
|
val solid = group.solidref.resolve(context.root)
|
||||||
?: error("Solid with tag ${group.solidref.ref} for volume ${group.name} not defined")
|
?: error("Solid with tag ${group.solidref.ref} for volume ${group.name} not defined")
|
||||||
//val material = group.materialref.resolve(context.root) ?: GDMLElement(group.materialref.ref)
|
|
||||||
|
|
||||||
when (context.solidAction(solid)) {
|
when (context.solidAction(solid)) {
|
||||||
GDMLTransformer.Action.ACCEPT -> {
|
GDMLTransformer.Action.ACCEPT -> {
|
||||||
@ -248,7 +266,5 @@ fun GDML.toVisual(block: GDMLTransformer.() -> Unit = {}): VisualGroup3D {
|
|||||||
|
|
||||||
val context = GDMLTransformer(this).apply(block)
|
val context = GDMLTransformer(this).apply(block)
|
||||||
|
|
||||||
return volume(context, world).also {
|
return context.finalize(volume(context, world))
|
||||||
context.finished(it)
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -1,6 +1,6 @@
|
|||||||
package hep.dataforge.vis.spatial.gdml
|
package hep.dataforge.vis.spatial.gdml
|
||||||
|
|
||||||
import hep.dataforge.names.toName
|
import hep.dataforge.vis.spatial.Visual3DPlugin
|
||||||
import hep.dataforge.vis.spatial.VisualGroup3D
|
import hep.dataforge.vis.spatial.VisualGroup3D
|
||||||
import nl.adaptivity.xmlutil.StAXReader
|
import nl.adaptivity.xmlutil.StAXReader
|
||||||
import scientifik.gdml.GDML
|
import scientifik.gdml.GDML
|
||||||
@ -19,17 +19,29 @@ fun main() {
|
|||||||
volume.name.startsWith("ecal") -> GDMLTransformer.Action.CACHE
|
volume.name.startsWith("ecal") -> GDMLTransformer.Action.CACHE
|
||||||
volume.name.startsWith("U") -> GDMLTransformer.Action.CACHE
|
volume.name.startsWith("U") -> GDMLTransformer.Action.CACHE
|
||||||
volume.name.startsWith("V") -> GDMLTransformer.Action.CACHE
|
volume.name.startsWith("V") -> GDMLTransformer.Action.CACHE
|
||||||
|
volume.name.startsWith("tof") -> GDMLTransformer.Action.CACHE
|
||||||
else -> GDMLTransformer.Action.ACCEPT
|
else -> GDMLTransformer.Action.ACCEPT
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
optimizeSingleChild = true
|
||||||
|
//optimizations = listOf(optimizeSingleChild)
|
||||||
onFinish = { printStatistics() }
|
onFinish = { printStatistics() }
|
||||||
}
|
}
|
||||||
|
|
||||||
val template = visual.getTemplate("volumes.ecal01mod".toName())
|
val string = Visual3DPlugin.json.stringify(VisualGroup3D.serializer(), visual)
|
||||||
println(template)
|
|
||||||
visual.flatMap { (it as? VisualGroup3D) ?: listOf(it) }.forEach {
|
val tmpFile = File.createTempFile("dataforge-visual", ".json")
|
||||||
if(it.parent==null) error("")
|
|
||||||
}
|
tmpFile.writeText(string)
|
||||||
|
|
||||||
|
println(tmpFile.canonicalPath)
|
||||||
|
|
||||||
|
|
||||||
|
// val template = visual.getTemplate("volumes.ecal01mod".toName())
|
||||||
|
// println(template)
|
||||||
|
// visual.flatMap { (it as? VisualGroup3D) ?: listOf(it) }.forEach {
|
||||||
|
// if(it.parent==null) error("")
|
||||||
|
// }
|
||||||
//readLine()
|
//readLine()
|
||||||
//val meta = visual.toMeta()
|
//val meta = visual.toMeta()
|
||||||
// val tmpFile = File.createTempFile("dataforge-visual", "json")
|
// val tmpFile = File.createTempFile("dataforge-visual", "json")
|
||||||
|
@ -6,7 +6,7 @@ plugins {
|
|||||||
}
|
}
|
||||||
|
|
||||||
scientifik{
|
scientifik{
|
||||||
serialization = true
|
withSerialization()
|
||||||
}
|
}
|
||||||
|
|
||||||
kotlin {
|
kotlin {
|
||||||
|
@ -33,10 +33,10 @@ class Proxy(val templateName: Name) : AbstractVisualObject(), VisualGroup, Visua
|
|||||||
/**
|
/**
|
||||||
* Recursively search for defined template in the parent
|
* Recursively search for defined template in the parent
|
||||||
*/
|
*/
|
||||||
val template: VisualObject3D by lazy {
|
val template: VisualObject3D
|
||||||
(parent as? VisualGroup3D)?.getTemplate(templateName)
|
get() = (parent as? VisualGroup3D)?.getTemplate(templateName)
|
||||||
?: error("Template with name $templateName not found in $parent")
|
?: error("Template with name $templateName not found in $parent")
|
||||||
}
|
|
||||||
|
|
||||||
override fun getProperty(name: Name, inherit: Boolean): MetaItem<*>? {
|
override fun getProperty(name: Name, inherit: Boolean): MetaItem<*>? {
|
||||||
return if (inherit) {
|
return if (inherit) {
|
||||||
|
@ -8,6 +8,7 @@ import hep.dataforge.io.MetaSerializer
|
|||||||
import hep.dataforge.io.NameSerializer
|
import hep.dataforge.io.NameSerializer
|
||||||
import hep.dataforge.meta.*
|
import hep.dataforge.meta.*
|
||||||
import hep.dataforge.names.Name
|
import hep.dataforge.names.Name
|
||||||
|
import hep.dataforge.vis.common.VisualObject
|
||||||
import hep.dataforge.vis.common.VisualPlugin
|
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
|
||||||
@ -38,13 +39,15 @@ class Visual3DPlugin(meta: Meta) : AbstractPlugin(meta) {
|
|||||||
contextual(NameTokenSerializer)
|
contextual(NameTokenSerializer)
|
||||||
contextual(MetaSerializer)
|
contextual(MetaSerializer)
|
||||||
contextual(ConfigSerializer)
|
contextual(ConfigSerializer)
|
||||||
polymorphic(VisualObject3D::class) {
|
|
||||||
|
polymorphic(VisualObject::class,VisualObject3D::class) {
|
||||||
VisualGroup3D::class with VisualGroup3D.serializer()
|
VisualGroup3D::class with VisualGroup3D.serializer()
|
||||||
Proxy::class with Proxy.serializer()
|
Proxy::class with Proxy.serializer()
|
||||||
Composite::class with Composite.serializer()
|
Composite::class with Composite.serializer()
|
||||||
Tube::class with Tube.serializer()
|
Tube::class with Tube.serializer()
|
||||||
Box::class with Box.serializer()
|
Box::class with Box.serializer()
|
||||||
Convex::class with Convex.serializer()
|
Convex::class with Convex.serializer()
|
||||||
|
addSubclass(Extruded.serializer())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,6 +12,7 @@ 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.VisualObject
|
import hep.dataforge.vis.common.VisualObject
|
||||||
|
import kotlinx.serialization.SerialName
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
import kotlinx.serialization.UseSerializers
|
import kotlinx.serialization.UseSerializers
|
||||||
|
|
||||||
@ -26,13 +27,13 @@ class VisualGroup3D() : AbstractVisualGroup(), VisualObject3D {
|
|||||||
field = value
|
field = value
|
||||||
}
|
}
|
||||||
|
|
||||||
@Serializable(ConfigSerializer::class)
|
public override var properties: Config? = null
|
||||||
override var properties: Config? = null
|
|
||||||
|
|
||||||
override var position: Point3D? = null
|
override var position: Point3D? = null
|
||||||
override var rotation: Point3D? = null
|
override var rotation: Point3D? = null
|
||||||
override var scale: Point3D? = null
|
override var scale: Point3D? = null
|
||||||
|
|
||||||
|
@SerialName("children")
|
||||||
private val _children = HashMap<NameToken, VisualObject>()
|
private val _children = HashMap<NameToken, VisualObject>()
|
||||||
override val children: Map<NameToken, VisualObject> get() = _children
|
override val children: Map<NameToken, VisualObject> get() = _children
|
||||||
|
|
||||||
|
@ -26,6 +26,24 @@ expect class Point3D(x: Number, y: Number, z: Number) {
|
|||||||
var z: Double
|
var z: Double
|
||||||
}
|
}
|
||||||
|
|
||||||
|
operator fun Point3D?.plus(other: Point3D?): Point3D? {
|
||||||
|
return when {
|
||||||
|
this == null && other == null -> null
|
||||||
|
this == null -> other
|
||||||
|
other == null -> this
|
||||||
|
else -> Point3D(x + other.x, y + other.y, z + other.z)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
operator fun Point3D?.minus(other: Point3D?): Point3D? {
|
||||||
|
return when {
|
||||||
|
this == null && other == null -> null
|
||||||
|
this == null -> Point3D(-other!!.x, -other.y, -other.z)
|
||||||
|
other == null -> this
|
||||||
|
else -> Point3D(x - other.x, y - other.y, z - other.z)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
operator fun Point3D.component1() = x
|
operator fun Point3D.component1() = x
|
||||||
operator fun Point3D.component2() = y
|
operator fun Point3D.component2() = y
|
||||||
operator fun Point3D.component3() = z
|
operator fun Point3D.component3() = z
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package hep.dataforge.vis.spatial
|
package hep.dataforge.vis.spatial
|
||||||
|
|
||||||
import hep.dataforge.vis.common.Colors
|
import hep.dataforge.vis.common.Colors
|
||||||
|
import hep.dataforge.vis.common.get
|
||||||
import kotlin.math.PI
|
import kotlin.math.PI
|
||||||
import kotlin.test.Test
|
import kotlin.test.Test
|
||||||
import kotlin.test.assertEquals
|
import kotlin.test.assertEquals
|
||||||
@ -9,7 +10,7 @@ class GroupTest {
|
|||||||
@Test
|
@Test
|
||||||
fun testGroupWithComposite() {
|
fun testGroupWithComposite() {
|
||||||
val group = VisualGroup3D().apply {
|
val group = VisualGroup3D().apply {
|
||||||
union {
|
union("union") {
|
||||||
box(100, 100, 100) {
|
box(100, 100, 100) {
|
||||||
z = 100
|
z = 100
|
||||||
rotationX = PI / 4
|
rotationX = PI / 4
|
||||||
@ -21,7 +22,7 @@ class GroupTest {
|
|||||||
"opacity" to 0.3
|
"opacity" to 0.3
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
intersect{
|
intersect("intersect") {
|
||||||
box(100, 100, 100) {
|
box(100, 100, 100) {
|
||||||
z = 100
|
z = 100
|
||||||
rotationX = PI / 4
|
rotationX = PI / 4
|
||||||
@ -31,7 +32,7 @@ class GroupTest {
|
|||||||
y = 300
|
y = 300
|
||||||
color(Colors.red)
|
color(Colors.red)
|
||||||
}
|
}
|
||||||
subtract{
|
subtract("subtract") {
|
||||||
box(100, 100, 100) {
|
box(100, 100, 100) {
|
||||||
z = 100
|
z = 100
|
||||||
rotationX = PI / 4
|
rotationX = PI / 4
|
||||||
@ -44,7 +45,7 @@ class GroupTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
assertEquals(3, group.count())
|
assertEquals(3, group.count())
|
||||||
assertEquals(300.0,group.toList()[1].y.toDouble())
|
assertEquals(300.0, (group["intersect"] as VisualObject3D).y.toDouble())
|
||||||
assertEquals(-300.0,group.toList()[2].y.toDouble())
|
assertEquals(-300.0, (group["subtract"] as VisualObject3D).y.toDouble())
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -15,6 +15,6 @@ class SerializationTest {
|
|||||||
val meta = cube.toMeta()
|
val meta = cube.toMeta()
|
||||||
println(meta)
|
println(meta)
|
||||||
val newCube = Box(Global,null, meta)
|
val newCube = Box(Global,null, meta)
|
||||||
assertEquals(cube,newCube)
|
assertEquals(cube.toMeta(),newCube.toMeta())
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user