diff --git a/demo/jupyter-playground/src/main/kotlin/hep/dataforge/playground/VisionForgePlayGroundForJupyter.kt b/demo/jupyter-playground/src/main/kotlin/hep/dataforge/playground/VisionForgePlayGroundForJupyter.kt index 95037870..42bc2bc1 100644 --- a/demo/jupyter-playground/src/main/kotlin/hep/dataforge/playground/VisionForgePlayGroundForJupyter.kt +++ b/demo/jupyter-playground/src/main/kotlin/hep/dataforge/playground/VisionForgePlayGroundForJupyter.kt @@ -3,23 +3,24 @@ package hep.dataforge.playground import hep.dataforge.context.Context import hep.dataforge.vision.VisionManager import hep.dataforge.vision.gdml.gdml -import hep.dataforge.vision.html.Page -import hep.dataforge.vision.html.embedVisionFragment -import hep.dataforge.vision.html.fragment -import hep.dataforge.vision.html.scriptHeader +import hep.dataforge.vision.html.* import hep.dataforge.vision.plotly.PlotlyPlugin import hep.dataforge.vision.plotly.VisionOfPlotly import hep.dataforge.vision.solid.SolidManager import hep.dataforge.vision.solid.solid import hep.dataforge.vision.visionManager import kotlinx.html.div +import kotlinx.html.id +import kotlinx.html.script import kotlinx.html.stream.createHTML +import kotlinx.html.unsafe import kscience.plotly.Plot import kscience.plotly.PlotlyFragment import org.jetbrains.kotlinx.jupyter.api.HTML import org.jetbrains.kotlinx.jupyter.api.Notebook import org.jetbrains.kotlinx.jupyter.api.annotations.JupyterLibrary import org.jetbrains.kotlinx.jupyter.api.libraries.* +import org.jetbrains.kotlinx.jupyter.api.libraries.ResourceLocation import space.kscience.gdml.Gdml @JupyterLibrary @@ -34,16 +35,25 @@ internal class VisionForgePlayGroundForJupyter : JupyterIntegration() { ResourcePathType.CLASSPATH_PATH))) val jsResource = LibraryResource(name = "VisionForge", type = ResourceType.JS, bundles = listOf(jsBundle)) + private var counter = 0 + + private fun produceHtmlVisionString(fragment: HtmlVisionFragment) = createHTML().div { + val id = "visionforge.vision[${counter++}]" + div { + this.id = id + embedVisionFragment(context.visionManager, fragment = fragment) + } + script { + type = "text/javascript" + unsafe { +"window.renderVisionsAt(\"$id\");" } + } + } + override fun Builder.onLoaded(notebook: Notebook?) { resource(jsResource) import("space.kscience.gdml.*", "kscience.plotly.*", "kscience.plotly.models.*") - onLoaded { - val header = scriptHeader("js/visionforge-playground.js", null, hep.dataforge.vision.html.ResourceLocation.EMBED) - display(HTML(createHTML().apply(header).finalize())) - } - render { gdmlModel -> val fragment = VisionManager.fragment { vision { @@ -53,11 +63,7 @@ internal class VisionForgePlayGroundForJupyter : JupyterIntegration() { } } - val html = createHTML().div { - embedVisionFragment(context.visionManager, fragment = fragment) - } - - HTML(html) + HTML(produceHtmlVisionString(fragment)) } render { plot -> @@ -67,11 +73,7 @@ internal class VisionForgePlayGroundForJupyter : JupyterIntegration() { } } - val html = createHTML().div { - embedVisionFragment(context.visionManager, fragment = fragment) - } - - HTML(html) + HTML( produceHtmlVisionString(fragment)) } render { fragment -> diff --git a/demo/playground/src/jsMain/kotlin/playgroundMain.kt b/demo/playground/src/jsMain/kotlin/playgroundMain.kt index b69e8a65..26397ad4 100644 --- a/demo/playground/src/jsMain/kotlin/playgroundMain.kt +++ b/demo/playground/src/jsMain/kotlin/playgroundMain.kt @@ -1,10 +1,14 @@ //import hep.dataforge.vision.plotly.withPlotly import hep.dataforge.vision.plotly.withPlotly +import hep.dataforge.vision.renderVisionsAt import hep.dataforge.vision.renderVisionsInWindow -import hep.dataforge.vision.solid.three.loadThreeJs +import hep.dataforge.vision.solid.three.withThreeJs +import kotlinx.browser.window fun main() { withPlotly() - loadThreeJs() + withThreeJs() renderVisionsInWindow() + window.asDynamic()["renderVisionsInWindow"] = ::renderVisionsInWindow + window.asDynamic()["renderVisionsAt"] = ::renderVisionsAt } \ No newline at end of file diff --git a/demo/playground/src/jvmMain/kotlin/gdmlCubes.kt b/demo/playground/src/jvmMain/kotlin/gdmlCubes.kt new file mode 100644 index 00000000..8a2d609f --- /dev/null +++ b/demo/playground/src/jvmMain/kotlin/gdmlCubes.kt @@ -0,0 +1,74 @@ +package hep.dataforge.vision.examples + +import hep.dataforge.misc.DFExperimental +import hep.dataforge.vision.VisionForge +import hep.dataforge.vision.VisionManager +import hep.dataforge.vision.gdml.gdml +import hep.dataforge.vision.html.ResourceLocation +import hep.dataforge.vision.html.fragment +import hep.dataforge.vision.solid.solid +import hep.dataforge.vision.solid.withSolids +import space.kscience.gdml.* + +internal val cubes = Gdml { + val center = define.position("center") + structure { + val air = ref("G4_AIR") + val tubeMaterial = ref("tube") + val boxMaterial = ref("box") + + val segment = solids.tube("segment", 20, 5.0) { + rmin = 17 + deltaphi = 60 + aunit = AUnit.DEG.title + } + 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) { + positionref = center.ref() + rotation { + z = 60 * i + unit = AUnit.DEG.title + } + } + } + } + + 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) { + position { + x = (-50 + i * 50) + y = (-50 + j * 50) + z = (-50 + k * 50) + } + rotation { + x = i * 120 + y = j * 120 + z = 120 * k + } + } + } + } + } + } + } +} + +@DFExperimental +fun main() { + val content = VisionManager.fragment { + vision("canvas") { + solid { + gdml(cubes) + } + } + } + + VisionForge.withSolids().makeVisionFile(content, resourceLocation = ResourceLocation.SYSTEM) +} \ No newline at end of file diff --git a/demo/playground/src/jvmMain/kotlin/plotlyVision.kt b/demo/playground/src/jvmMain/kotlin/plotlyVision.kt index 22b0863b..93f79ace 100644 --- a/demo/playground/src/jvmMain/kotlin/plotlyVision.kt +++ b/demo/playground/src/jvmMain/kotlin/plotlyVision.kt @@ -3,6 +3,7 @@ package hep.dataforge.vision.examples import hep.dataforge.misc.DFExperimental import hep.dataforge.vision.VisionForge import hep.dataforge.vision.VisionManager +import hep.dataforge.vision.html.ResourceLocation import hep.dataforge.vision.html.fragment import hep.dataforge.vision.plotly.plotly import hep.dataforge.vision.plotly.withPlotly @@ -21,5 +22,5 @@ fun main() { } } - VisionForge.withPlotly().makeVisionFile(fragment) + VisionForge.withPlotly().makeVisionFile(fragment, resourceLocation = ResourceLocation.SYSTEM) } \ No newline at end of file diff --git a/demo/playground/src/jvmMain/kotlin/simpleCube.kt b/demo/playground/src/jvmMain/kotlin/simpleCube.kt index 9b43ff90..159e908b 100644 --- a/demo/playground/src/jvmMain/kotlin/simpleCube.kt +++ b/demo/playground/src/jvmMain/kotlin/simpleCube.kt @@ -9,7 +9,7 @@ import hep.dataforge.vision.solid.box import hep.dataforge.vision.solid.solid import hep.dataforge.vision.solid.withSolids -@OptIn(DFExperimental::class) +@DFExperimental fun main() { val content = VisionManager.fragment { vision("canvas") { diff --git a/visionforge-core/src/commonMain/kotlin/hep/dataforge/vision/html/VisionTagConsumer.kt b/visionforge-core/src/commonMain/kotlin/hep/dataforge/vision/html/VisionTagConsumer.kt index 0a536c90..9f3db8c1 100644 --- a/visionforge-core/src/commonMain/kotlin/hep/dataforge/vision/html/VisionTagConsumer.kt +++ b/visionforge-core/src/commonMain/kotlin/hep/dataforge/vision/html/VisionTagConsumer.kt @@ -83,7 +83,7 @@ public abstract class VisionTagConsumer( visionProvider: VisionOutput.() -> Vision, ): T = vision(name.toName(), visionProvider) - public inline fun TagConsumer.vision( + public fun TagConsumer.vision( vision: Vision, ): T = vision("vision[${vision.hashCode()}]".toName(), vision) diff --git a/visionforge-core/src/jsMain/kotlin/hep/dataforge/vision/VisionForge.kt b/visionforge-core/src/jsMain/kotlin/hep/dataforge/vision/VisionForge.kt index 6f6ca28a..fc3cd8a6 100644 --- a/visionforge-core/src/jsMain/kotlin/hep/dataforge/vision/VisionForge.kt +++ b/visionforge-core/src/jsMain/kotlin/hep/dataforge/vision/VisionForge.kt @@ -4,19 +4,32 @@ import hep.dataforge.context.Context import hep.dataforge.context.Global import hep.dataforge.vision.client.VisionClient import hep.dataforge.vision.client.renderAllVisions +import hep.dataforge.vision.client.renderAllVisionsAt +import kotlinx.browser.document import kotlinx.browser.window -public actual val VisionForge: Context = Global.context("VisionForge").apply{ +public actual val VisionForge: Context = Global.context("VisionForge").apply { plugins.fetch(VisionManager) plugins.fetch(VisionClient) } + /** * Render all visions in this [window] using current global state of [VisionForge] */ @JsExport -public fun renderVisionsInWindow(){ +public fun renderVisionsInWindow() { window.onload = { VisionForge.plugins[VisionClient]?.renderAllVisions() } +} + +@JsExport +public fun renderVisionsAt(id: String) { + val element = document.getElementById(id) + if (element != null) { + VisionForge.plugins[VisionClient]?.renderAllVisionsAt(element) + } else { + console.warn("Element with id $id not found") + } } \ No newline at end of file diff --git a/visionforge-core/src/jsMain/kotlin/hep/dataforge/vision/client/VisionClient.kt b/visionforge-core/src/jsMain/kotlin/hep/dataforge/vision/client/VisionClient.kt index edd5ae4d..f6799fc0 100644 --- a/visionforge-core/src/jsMain/kotlin/hep/dataforge/vision/client/VisionClient.kt +++ b/visionforge-core/src/jsMain/kotlin/hep/dataforge/vision/client/VisionClient.kt @@ -43,8 +43,16 @@ public class VisionClient : AbstractPlugin() { private fun getRenderers() = context.gather(ElementVisionRenderer.TYPE).values - private fun findRendererFor(vision: Vision): ElementVisionRenderer? = - getRenderers().maxByOrNull { it.rateVision(vision) } + private fun findRendererFor(vision: Vision): ElementVisionRenderer? { + return getRenderers().mapNotNull { + val rating = it.rateVision(vision) + if (rating > 0) { + rating to it + } else { + null + } + }.maxByOrNull { it.first }?.second + } private fun Element.getEmbeddedData(className: String): String? = getElementsByClassName(className)[0]?.innerHTML diff --git a/visionforge-core/src/jvmMain/kotlin/hep/dataforge/vision/html/headers.kt b/visionforge-core/src/jvmMain/kotlin/hep/dataforge/vision/html/headers.kt index 45fde55a..ac9f7127 100644 --- a/visionforge-core/src/jvmMain/kotlin/hep/dataforge/vision/html/headers.kt +++ b/visionforge-core/src/jvmMain/kotlin/hep/dataforge/vision/html/headers.kt @@ -8,6 +8,10 @@ import kotlinx.html.unsafe import java.nio.file.Files import java.nio.file.Path import java.nio.file.StandardOpenOption +import java.security.MessageDigest +import kotlin.io.path.ExperimentalPathApi +import kotlin.io.path.readText + /** * The location of resources for plot. @@ -37,21 +41,29 @@ public enum class ResourceLocation { internal const val VISIONFORGE_ASSETS_PATH = ".dataforge/vision/assets" +private fun ByteArray.toHexString() = asUByteArray().joinToString("") { it.toString(16).padStart(2, '0') } + /** * Check if the asset exists in given local location and put it there if it does not * @param */ +@OptIn(ExperimentalPathApi::class) internal fun checkOrStoreFile(htmlPath: Path, filePath: Path, resource: String): Path { + //TODO add logging val fullPath = htmlPath.resolveSibling(filePath).toAbsolutePath().resolve(resource) - if (Files.exists(fullPath)) { - //TODO checksum - } else { - //TODO add logging + val bytes = VisionManager::class.java.getResourceAsStream("/$resource").readAllBytes() + val md = MessageDigest.getInstance("MD5") - val bytes = VisionManager::class.java.getResourceAsStream("/$resource").readAllBytes() + val checksum = md.digest(bytes).toHexString() + + val md5File = fullPath.resolveSibling(fullPath.fileName.toString() + ".md5") + val skip: Boolean = Files.exists(fullPath) && Files.exists(md5File) && md5File.readText() == checksum + + if (!skip) { Files.createDirectories(fullPath.parent) - Files.write(fullPath, bytes, StandardOpenOption.CREATE_NEW, StandardOpenOption.WRITE) + Files.write(fullPath, bytes, StandardOpenOption.CREATE, StandardOpenOption.WRITE) + Files.write(md5File, checksum.encodeToByteArray(), StandardOpenOption.CREATE, StandardOpenOption.WRITE) } return if (htmlPath.isAbsolute && fullPath.startsWith(htmlPath.parent)) { diff --git a/visionforge-gdml/src/jvmTest/kotlin/hep/dataforge/vision/gdml/TestConvertor.kt b/visionforge-gdml/src/jvmTest/kotlin/hep/dataforge/vision/gdml/TestConvertor.kt index f5e22263..d599cf07 100644 --- a/visionforge-gdml/src/jvmTest/kotlin/hep/dataforge/vision/gdml/TestConvertor.kt +++ b/visionforge-gdml/src/jvmTest/kotlin/hep/dataforge/vision/gdml/TestConvertor.kt @@ -1,38 +1,36 @@ package hep.dataforge.vision.gdml +import hep.dataforge.names.toName import hep.dataforge.vision.solid.SolidManager import space.kscience.gdml.Gdml -import nl.adaptivity.xmlutil.StAXReader import org.junit.jupiter.api.Test +import space.kscience.gdml.decodeFromStream +import kotlin.test.assertNotNull class TestConvertor { @Test fun testBMNGeometry() { val stream = javaClass.getResourceAsStream("/gdml/BM@N.gdml") - val xmlReader = StAXReader(stream, "UTF-8") - val xml = Gdml.format.parse(Gdml.serializer(), xmlReader) - val vision = xml.toVision() - println(SolidManager.encodeToString(vision)) + val gdml = Gdml.decodeFromStream(stream) + val vision = gdml.toVision() + //println(SolidManager.encodeToString(vision)) } @Test fun testCubes() { val stream = javaClass.getResourceAsStream("/gdml/cubes.gdml") - - val xmlReader = StAXReader(stream, "UTF-8") - val xml = Gdml.format.parse(Gdml.serializer(), xmlReader) - val visual = xml.toVision() - // println(visual) + val gdml = Gdml.decodeFromStream(stream) + val vision = gdml.toVision() + assertNotNull(vision.getPrototype("solids.box".toName())) + //println(SolidManager.encodeToString(vision)) } @Test fun testSimple() { val stream = javaClass.getResourceAsStream("/gdml/simple1.gdml") - - val xmlReader = StAXReader(stream, "UTF-8") - val xml = Gdml.format.parse(Gdml.serializer(), xmlReader) - val vision = xml.toVision() - println(SolidManager.encodeToString(vision)) + val gdml = Gdml.decodeFromStream(stream) + val vision = gdml.toVision() + //println(SolidManager.encodeToString(vision)) } } \ No newline at end of file diff --git a/visionforge-gdml/src/jvmTest/kotlin/hep/dataforge/vision/gdml/TestCubes.kt b/visionforge-gdml/src/jvmTest/kotlin/hep/dataforge/vision/gdml/TestCubes.kt new file mode 100644 index 00000000..adaca24a --- /dev/null +++ b/visionforge-gdml/src/jvmTest/kotlin/hep/dataforge/vision/gdml/TestCubes.kt @@ -0,0 +1,74 @@ +package hep.dataforge.vision.gdml + +import hep.dataforge.names.toName +import hep.dataforge.vision.solid.SolidGroup +import hep.dataforge.vision.solid.SolidManager +import org.junit.jupiter.api.Test +import space.kscience.gdml.* +import kotlin.test.assertNotNull + +class TestCubes { + internal val cubes = Gdml { + val center = define.position("center") + structure { + val air = ref("G4_AIR") + val tubeMaterial = ref("tube") + val boxMaterial = ref("box") + + val segment = solids.tube("segment", 20, 5.0) { + rmin = 17 + deltaphi = 60 + aunit = AUnit.DEG.title + } + 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) { + positionref = center.ref() + rotation { + z = 60 * i + unit = AUnit.DEG.title + } + } + } + } + + 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) { + position { + x = (-50 + i * 50) + y = (-50 + j * 50) + z = (-50 + k * 50) + } + rotation { + x = i * 120 + y = j * 120 + z = 120 * k + } + } + } + } + } + } + } + } + + @Test + fun testCubesDirect(){ + val vision = cubes.toVision() + assertNotNull(vision.getPrototype("solids.smallBox".toName())) + } + + @Test + fun testCubesReSerialize(){ + val vision = cubes.toVision() + val serialized = SolidManager.encodeToString(vision) + val deserialized = SolidManager.decodeFromString(serialized) as SolidGroup + assertNotNull(deserialized.getPrototype("solids.smallBox".toName())) + } +} \ No newline at end of file diff --git a/visionforge-plotly/src/jsMain/kotlin/hep/dataforge/vision/plotly/plotlyJs.kt b/visionforge-plotly/src/jsMain/kotlin/hep/dataforge/vision/plotly/plotlyJs.kt index 097c7a54..601c255f 100644 --- a/visionforge-plotly/src/jsMain/kotlin/hep/dataforge/vision/plotly/plotlyJs.kt +++ b/visionforge-plotly/src/jsMain/kotlin/hep/dataforge/vision/plotly/plotlyJs.kt @@ -2,6 +2,8 @@ package hep.dataforge.vision.plotly import hep.dataforge.context.* import hep.dataforge.meta.Meta +import hep.dataforge.names.Name +import hep.dataforge.names.asName import hep.dataforge.vision.Vision import hep.dataforge.vision.VisionForge import hep.dataforge.vision.VisionPlugin @@ -26,11 +28,18 @@ public actual class PlotlyPlugin : VisionPlugin(), ElementVisionRenderer { } override fun render(element: Element, vision: Vision, meta: Meta) { - val plot = (vision as? VisionOfPlotly)?.plot ?: error("Only VisionOfPlotly visions are supported") + val plot = (vision as? VisionOfPlotly)?.plot ?: error("VisionOfPlotly expected but ${vision::class} found") val config = PlotlyConfig.read(meta) element.plot(plot, config) } + override fun content(target: String): Map { + return when (target) { + ElementVisionRenderer.TYPE -> mapOf("plotly".asName() to this) + else -> super.content(target) + } + } + public companion object : PluginFactory { override val tag: PluginTag = PluginTag("vision.plotly", PluginTag.DATAFORGE_GROUP) override val type: KClass = PlotlyPlugin::class diff --git a/visionforge-solid/src/commonMain/kotlin/hep/dataforge/vision/solid/Box.kt b/visionforge-solid/src/commonMain/kotlin/hep/dataforge/vision/solid/Box.kt index c5a81fc6..9f13216b 100644 --- a/visionforge-solid/src/commonMain/kotlin/hep/dataforge/vision/solid/Box.kt +++ b/visionforge-solid/src/commonMain/kotlin/hep/dataforge/vision/solid/Box.kt @@ -35,27 +35,6 @@ public class Box( geometryBuilder.face4(node8, node5, node6, node7) } -// override fun equals(other: Any?): Boolean { -// if (this === other) return true -// if (other == null || this::class != other::class) return false -// -// other as Box -// -// if (xSize != other.xSize) return false -// if (ySize != other.ySize) return false -// if (zSize != other.zSize) return false -// -// return solidEquals(this, other) -// } -// -// override fun hashCode(): Int { -// var result = xSize.hashCode() -// result = 31 * result + ySize.hashCode() -// result = 31 * result + zSize.hashCode() -// return 31 * result + Solid.solidHashCode(this) -// } - - public companion object { } diff --git a/visionforge-solid/src/commonMain/kotlin/hep/dataforge/vision/solid/SolidGroup.kt b/visionforge-solid/src/commonMain/kotlin/hep/dataforge/vision/solid/SolidGroup.kt index e7855cd5..28e0e4e3 100644 --- a/visionforge-solid/src/commonMain/kotlin/hep/dataforge/vision/solid/SolidGroup.kt +++ b/visionforge-solid/src/commonMain/kotlin/hep/dataforge/vision/solid/SolidGroup.kt @@ -28,9 +28,13 @@ public interface PrototypeHolder { @Serializable @SerialName("group.solid") public class SolidGroup( - @Serializable(Prototypes.Companion::class) @SerialName("prototypes") private var prototypes: MutableVisionGroup? = null, + @Serializable(Prototypes.Companion::class) @SerialName("prototypes") internal var prototypes: MutableVisionGroup? = null, ) : VisionGroupBase(), Solid, PrototypeHolder { + init { + prototypes?.parent = this + } + override val descriptor: NodeDescriptor get() = Solid.descriptor /** diff --git a/visionforge-solid/src/commonTest/kotlin/hep/dataforge/vision/solid/SolidPluginTest.kt b/visionforge-solid/src/commonTest/kotlin/hep/dataforge/vision/solid/SolidPluginTest.kt index a18207c8..1da06a02 100644 --- a/visionforge-solid/src/commonTest/kotlin/hep/dataforge/vision/solid/SolidPluginTest.kt +++ b/visionforge-solid/src/commonTest/kotlin/hep/dataforge/vision/solid/SolidPluginTest.kt @@ -8,21 +8,21 @@ import kotlin.test.assertEquals class SolidPluginTest { val vision = SolidGroup { - box(100,100,100, name = "aBox") + box(100, 100, 100, name = "aBox") - sphere(100,name = "aSphere"){ + sphere(100, name = "aSphere") { z = 200 } } @DFExperimental @Test - fun testPluginConverter(){ + fun testPluginConverter() { val visionManager = Global.plugins.fetch(SolidManager).visionManager val meta = visionManager.encodeToMeta(vision) val reconstructed = visionManager.decodeFromMeta(meta) as SolidGroup - assertEquals(vision["aBox"],reconstructed["aBox"]) + assertEquals(visionManager.encodeToJsonElement(vision["aBox"]!!), visionManager.encodeToJsonElement(reconstructed["aBox"]!!)) } } \ No newline at end of file diff --git a/visionforge-solid/src/commonTest/kotlin/hep/dataforge/vision/solid/SolidReferenceTest.kt b/visionforge-solid/src/commonTest/kotlin/hep/dataforge/vision/solid/SolidReferenceTest.kt index 1ac2738f..bb38316e 100644 --- a/visionforge-solid/src/commonTest/kotlin/hep/dataforge/vision/solid/SolidReferenceTest.kt +++ b/visionforge-solid/src/commonTest/kotlin/hep/dataforge/vision/solid/SolidReferenceTest.kt @@ -3,6 +3,8 @@ package hep.dataforge.vision.solid import hep.dataforge.vision.get import hep.dataforge.vision.style import hep.dataforge.vision.useStyle +import kotlinx.serialization.json.Json +import kotlinx.serialization.json.encodeToJsonElement import kotlin.test.Test import kotlin.test.assertEquals @@ -22,4 +24,11 @@ class SolidReferenceTest { fun testReferenceProperty(){ assertEquals("blue", (groupWithReference["test"] as Solid).color.string) } + + @Test + fun testReferenceSerialization(){ + val serialized = SolidManager.jsonForSolids.encodeToJsonElement(groupWithReference) + val deserialized = SolidManager.jsonForSolids.decodeFromJsonElement(SolidGroup.serializer(), serialized) + assertEquals("blue", (deserialized["test"] as Solid).color.string) + } } \ No newline at end of file diff --git a/visionforge-threejs/src/main/kotlin/hep/dataforge/vision/solid/three/ThreePlugin.kt b/visionforge-threejs/src/main/kotlin/hep/dataforge/vision/solid/three/ThreePlugin.kt index 95020784..246e90dd 100644 --- a/visionforge-threejs/src/main/kotlin/hep/dataforge/vision/solid/three/ThreePlugin.kt +++ b/visionforge-threejs/src/main/kotlin/hep/dataforge/vision/solid/three/ThreePlugin.kt @@ -126,9 +126,8 @@ public class ThreePlugin : AbstractPlugin(), ElementVisionRenderer { } } - override fun rateVision(vision: Vision): Int { - return if (vision is Solid) ElementVisionRenderer.DEFAULT_RATING else ElementVisionRenderer.ZERO_RATING - } + override fun rateVision(vision: Vision): Int = + if (vision is Solid) ElementVisionRenderer.DEFAULT_RATING else ElementVisionRenderer.ZERO_RATING public fun renderSolid( element: Element, @@ -141,7 +140,7 @@ public class ThreePlugin : AbstractPlugin(), ElementVisionRenderer { override fun render(element: Element, vision: Vision, meta: Meta) { renderSolid( element, - vision as? Solid ?: error("Solid expected but ${vision::class} is found"), + vision as? Solid ?: error("Solid expected but ${vision::class} found"), Canvas3DOptions.read(meta) ) } @@ -157,7 +156,7 @@ public class ThreePlugin : AbstractPlugin(), ElementVisionRenderer { * Ensure that [ThreePlugin] is loaded in the global [VisionForge] context */ @JsExport -public fun loadThreeJs() { +public fun withThreeJs() { VisionForge.plugins.fetch(ThreePlugin) } diff --git a/visionforge-threejs/visionforge-threejs-server/src/jsMain/kotlin/hep/dataforge/vision/three/server/jsMain.kt b/visionforge-threejs/visionforge-threejs-server/src/jsMain/kotlin/hep/dataforge/vision/three/server/jsMain.kt index ab4b5e46..268e1a8e 100644 --- a/visionforge-threejs/visionforge-threejs-server/src/jsMain/kotlin/hep/dataforge/vision/three/server/jsMain.kt +++ b/visionforge-threejs/visionforge-threejs-server/src/jsMain/kotlin/hep/dataforge/vision/three/server/jsMain.kt @@ -1,9 +1,9 @@ package hep.dataforge.vision.three.server import hep.dataforge.vision.renderVisionsInWindow -import hep.dataforge.vision.solid.three.loadThreeJs +import hep.dataforge.vision.solid.three.withThreeJs public fun main() { - loadThreeJs() + withThreeJs() renderVisionsInWindow() } \ No newline at end of file