diff --git a/demo/gdml/src/jsMain/resources/index.html b/demo/gdml/src/jsMain/resources/index.html
index ba6c6868..8f5ca1ef 100644
--- a/demo/gdml/src/jsMain/resources/index.html
+++ b/demo/gdml/src/jsMain/resources/index.html
@@ -5,7 +5,6 @@
Three js demo for particle physics
-
diff --git a/demo/playground/src/jvmMain/kotlin/gdmCurve.kt b/demo/playground/src/jvmMain/kotlin/gdmCurve.kt
index 12981241..2b9aef01 100644
--- a/demo/playground/src/jvmMain/kotlin/gdmCurve.kt
+++ b/demo/playground/src/jvmMain/kotlin/gdmCurve.kt
@@ -2,7 +2,7 @@ package space.kscience.visionforge.examples
import space.kscience.dataforge.context.Context
import space.kscience.gdml.*
-import space.kscience.visionforge.gdml.gdml
+import space.kscience.visionforge.gdml.toVision
import space.kscience.visionforge.solid.Solids
fun main() {
@@ -12,7 +12,7 @@ fun main() {
context.makeVisionFile {
vision("canvas") {
- gdml {
+ Gdml {
// geometry variables
val worldSize = 500
// chamber
@@ -220,6 +220,8 @@ fun main() {
}
}
}
+ }.toVision {
+ this.solidAction
}
}
}
diff --git a/demo/playground/src/jvmMain/kotlin/gdmlIaxo.kt b/demo/playground/src/jvmMain/kotlin/gdmlIaxo.kt
index 10e81070..a9070af7 100644
--- a/demo/playground/src/jvmMain/kotlin/gdmlIaxo.kt
+++ b/demo/playground/src/jvmMain/kotlin/gdmlIaxo.kt
@@ -10,9 +10,7 @@ fun main() {
plugin(Solids)
}
- context.makeVisionFile{
- vision("canvas") {
- GdmlShowCase.babyIaxo().toVision()
- }
+ context.makeVisionFile {
+ vision("canvas") { GdmlShowCase.babyIaxo().toVision() }
}
}
\ No newline at end of file
diff --git a/jupyter/visionforge-gdml-jupyter/src/jvmMain/kotlin/GdmlForJupyter.kt b/jupyter/visionforge-gdml-jupyter/src/jvmMain/kotlin/GdmlForJupyter.kt
index 86041d32..31d1d9aa 100644
--- a/jupyter/visionforge-gdml-jupyter/src/jvmMain/kotlin/GdmlForJupyter.kt
+++ b/jupyter/visionforge-gdml-jupyter/src/jvmMain/kotlin/GdmlForJupyter.kt
@@ -1,10 +1,6 @@
package space.kscience.visionforge.gdml.jupyter
-import kotlinx.html.div
-import kotlinx.html.id
-import kotlinx.html.script
import kotlinx.html.stream.createHTML
-import kotlinx.html.unsafe
import org.jetbrains.kotlinx.jupyter.api.HTML
import org.jetbrains.kotlinx.jupyter.api.annotations.JupyterLibrary
import org.jetbrains.kotlinx.jupyter.api.libraries.JupyterIntegration
@@ -16,7 +12,7 @@ import space.kscience.visionforge.Vision
import space.kscience.visionforge.gdml.toVision
import space.kscience.visionforge.html.HtmlVisionFragment
import space.kscience.visionforge.html.Page
-import space.kscience.visionforge.html.embedVisionFragment
+import space.kscience.visionforge.html.embedAndRenderVisionFragment
import space.kscience.visionforge.solid.Solids
import space.kscience.visionforge.visionManager
@@ -30,17 +26,9 @@ internal class GdmlForJupyter : JupyterIntegration() {
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 { +"VisionForge.renderVisionsAt(\"$id\");" }
- }
- }
+ private fun produceHtmlVisionString(fragment: HtmlVisionFragment) = createHTML().apply {
+ embedAndRenderVisionFragment(context.visionManager, counter++, fragment)
+ }.finalize()
override fun Builder.onLoaded() {
@@ -62,19 +50,12 @@ internal class GdmlForJupyter : JupyterIntegration() {
"space.kscience.visionforge.gdml.jupyter.*"
)
- render { gdmlModel ->
- val fragment = HtmlVisionFragment {
- vision(gdmlModel.toVision())
- }
- HTML(produceHtmlVisionString(fragment))
+ render { vision ->
+ HTML(produceHtmlVisionString { vision(vision) })
}
- render { vision ->
- val fragment = HtmlVisionFragment {
- vision(vision)
- }
-
- HTML(produceHtmlVisionString(fragment))
+ render { gdmlModel ->
+ HTML(produceHtmlVisionString { vision(gdmlModel.toVision()) })
}
render { page ->
diff --git a/ui/react/build.gradle.kts b/ui/react/build.gradle.kts
index 86c5068f..f20a63b8 100644
--- a/ui/react/build.gradle.kts
+++ b/ui/react/build.gradle.kts
@@ -8,5 +8,6 @@ dependencies{
api(project(":visionforge-solid"))
api("org.jetbrains:kotlin-styled:5.2.3-$kotlinWrappersVersion")
api("org.jetbrains:kotlin-react-dom:17.0.2-$kotlinWrappersVersion")
+// implementation(npm("react-select","4.3.0"))
implementation(project(":visionforge-threejs"))
}
\ No newline at end of file
diff --git a/ui/react/src/main/kotlin/space/kscience/visionforge/react/MultiSelectChooser.kt b/ui/react/src/main/kotlin/space/kscience/visionforge/react/MultiSelectChooser.kt
new file mode 100644
index 00000000..497256c8
--- /dev/null
+++ b/ui/react/src/main/kotlin/space/kscience/visionforge/react/MultiSelectChooser.kt
@@ -0,0 +1,42 @@
+package space.kscience.visionforge.react
+
+import kotlinx.html.js.onChangeFunction
+import org.w3c.dom.HTMLOptionElement
+import org.w3c.dom.HTMLSelectElement
+import org.w3c.dom.asList
+import org.w3c.dom.events.Event
+import react.FunctionalComponent
+import react.dom.option
+import react.dom.select
+import react.functionalComponent
+import react.useState
+import space.kscience.dataforge.meta.value
+import space.kscience.dataforge.values.asValue
+import space.kscience.dataforge.values.string
+
+@JsExport
+public val MultiSelectChooser: FunctionalComponent =
+ functionalComponent("MultiSelectChooser") { props ->
+ var selectedItems by useState { props.item.value?.list ?: emptyList() }
+
+ val onChange: (Event) -> Unit = { event: Event ->
+ val newSelected= (event.target as HTMLSelectElement).selectedOptions.asList()
+ .map { (it as HTMLOptionElement).value.asValue() }
+ props.valueChanged?.invoke(newSelected.asValue())
+ selectedItems = newSelected
+ }
+
+ select {
+ attrs {
+ multiple = true
+ values = selectedItems.mapTo(HashSet()) { it.string }
+ onChangeFunction = onChange
+ }
+ props.descriptor?.allowedValues?.forEach { optionValue ->
+ option {
+ +optionValue.string
+ }
+ }
+
+ }
+ }
\ No newline at end of file
diff --git a/ui/react/src/main/kotlin/space/kscience/visionforge/react/valueChooser.kt b/ui/react/src/main/kotlin/space/kscience/visionforge/react/valueChooser.kt
index feab99d8..b0b448bb 100644
--- a/ui/react/src/main/kotlin/space/kscience/visionforge/react/valueChooser.kt
+++ b/ui/react/src/main/kotlin/space/kscience/visionforge/react/valueChooser.kt
@@ -152,6 +152,7 @@ public val ValueChooser: FunctionalComponent = functionalComp
when {
rawInput -> child(StringValueChooser, props)
descriptor?.widgetType == "color" -> child(ColorValueChooser, props)
+ descriptor?.widgetType == "multiSelect" -> child(MultiSelectChooser, props)
type == ValueType.BOOLEAN -> child(BooleanValueChooser, props)
type == ValueType.NUMBER -> child(NumberValueChooser, props)
descriptor?.allowedValues?.isNotEmpty() ?: false -> child(ComboValueChooser, props)
diff --git a/visionforge-core/src/commonMain/kotlin/space/kscience/visionforge/StyleReference.kt b/visionforge-core/src/commonMain/kotlin/space/kscience/visionforge/StyleReference.kt
index e25315aa..961e937a 100644
--- a/visionforge-core/src/commonMain/kotlin/space/kscience/visionforge/StyleReference.kt
+++ b/visionforge-core/src/commonMain/kotlin/space/kscience/visionforge/StyleReference.kt
@@ -2,7 +2,8 @@ package space.kscience.visionforge
import space.kscience.dataforge.meta.Meta
import space.kscience.dataforge.meta.MetaBuilder
-import space.kscience.dataforge.misc.DFExperimental
+import space.kscience.dataforge.meta.Scheme
+import space.kscience.dataforge.meta.Specification
import kotlin.properties.ReadOnlyProperty
/**
@@ -23,11 +24,23 @@ public fun Vision.useStyle(reference: StyleReference) {
useStyle(reference.name)
}
-@DFExperimental
@VisionBuilder
-public fun VisionGroup.style(builder: MetaBuilder.() -> Unit): ReadOnlyProperty =
- ReadOnlyProperty { _, property ->
- val styleName = property.name
- styleSheet.define(styleName, Meta(builder))
- StyleReference(this, styleName)
- }
\ No newline at end of file
+public fun VisionGroup.style(
+ styleKey: String? = null,
+ builder: MetaBuilder.() -> Unit,
+): ReadOnlyProperty = ReadOnlyProperty { _, property ->
+ val styleName = styleKey ?: property.name
+ styleSheet.define(styleName, Meta(builder))
+ StyleReference(this, styleName)
+}
+
+@VisionBuilder
+public fun VisionGroup.style(
+ spec: Specification,
+ styleKey: String? = null,
+ builder: T.() -> Unit,
+): ReadOnlyProperty = ReadOnlyProperty { _, property ->
+ val styleName = styleKey ?: property.name
+ styleSheet.define(styleName, spec(builder).toMeta())
+ StyleReference(this, styleName)
+}
\ No newline at end of file
diff --git a/visionforge-core/src/commonMain/kotlin/space/kscience/visionforge/html/staticHtmlRender.kt b/visionforge-core/src/commonMain/kotlin/space/kscience/visionforge/html/HtmlVisionRenderer.kt
similarity index 65%
rename from visionforge-core/src/commonMain/kotlin/space/kscience/visionforge/html/staticHtmlRender.kt
rename to visionforge-core/src/commonMain/kotlin/space/kscience/visionforge/html/HtmlVisionRenderer.kt
index e246572e..2e902d4d 100644
--- a/visionforge-core/src/commonMain/kotlin/space/kscience/visionforge/html/staticHtmlRender.kt
+++ b/visionforge-core/src/commonMain/kotlin/space/kscience/visionforge/html/HtmlVisionRenderer.kt
@@ -2,6 +2,7 @@ package space.kscience.visionforge.html
import kotlinx.html.*
import space.kscience.dataforge.meta.Meta
+import space.kscience.dataforge.misc.DFExperimental
import space.kscience.dataforge.names.Name
import space.kscience.visionforge.Vision
import space.kscience.visionforge.VisionManager
@@ -35,20 +36,19 @@ public fun FlowContent.embedVisionFragment(
fragment: HtmlVisionFragment,
): Map = consumer.embedVisionFragment(manager, idPrefix, fragment)
-public typealias HtmlVisionRenderer = FlowContent.(name: Name, vision: Vision, meta: Meta) -> Unit
-public fun FlowContent.renderVisionFragment(
- renderer: DIV.(name: Name, vision: Vision, meta: Meta) -> Unit,
- idPrefix: String? = null,
- fragment: HtmlVisionFragment,
-): Map {
- val visionMap = HashMap()
- val consumer = object : VisionTagConsumer(consumer, idPrefix) {
- override fun DIV.renderVision(name: Name, vision: Vision, outputMeta: Meta) {
- visionMap[name] = vision
- renderer(name, vision, outputMeta)
+internal const val RENDER_FUNCTION_NAME = "renderAllVisionsById"
+
+@DFExperimental
+public fun TagConsumer<*>.embedAndRenderVisionFragment(manager: VisionManager, id: Any, fragment: HtmlVisionFragment){
+ div {
+ div {
+ this.id = id.toString()
+ embedVisionFragment(manager, fragment = fragment)
+ }
+ script {
+ type = "text/javascript"
+ unsafe { +"window.${RENDER_FUNCTION_NAME}(\"$id\");" }
}
}
- fragment(consumer)
- return visionMap
}
\ No newline at end of file
diff --git a/visionforge-core/src/commonMain/kotlin/space/kscience/visionforge/html/VisionTagConsumer.kt b/visionforge-core/src/commonMain/kotlin/space/kscience/visionforge/html/VisionTagConsumer.kt
index aa8e6fcb..967e1851 100644
--- a/visionforge-core/src/commonMain/kotlin/space/kscience/visionforge/html/VisionTagConsumer.kt
+++ b/visionforge-core/src/commonMain/kotlin/space/kscience/visionforge/html/VisionTagConsumer.kt
@@ -66,7 +66,9 @@ public abstract class VisionTagConsumer(
}
}
}
- vision?.let { renderVision(name, it, outputMeta) }
+ vision?.let {
+ renderVision(name, it, outputMeta)
+ }
}
@OptIn(DFExperimental::class)
diff --git a/visionforge-core/src/commonMain/kotlin/space/kscience/visionforge/schemeDesctiptors.kt b/visionforge-core/src/commonMain/kotlin/space/kscience/visionforge/schemeDesctiptors.kt
index f1a5fb1c..8c43d0e0 100644
--- a/visionforge-core/src/commonMain/kotlin/space/kscience/visionforge/schemeDesctiptors.kt
+++ b/visionforge-core/src/commonMain/kotlin/space/kscience/visionforge/schemeDesctiptors.kt
@@ -4,7 +4,7 @@ import space.kscience.dataforge.meta.Scheme
import space.kscience.dataforge.meta.SchemeSpec
import space.kscience.dataforge.meta.descriptors.NodeDescriptor
import space.kscience.dataforge.meta.descriptors.NodeDescriptorBuilder
-import space.kscience.dataforge.meta.descriptors.ValueDescriptor
+import space.kscience.dataforge.meta.descriptors.ValueDescriptorBuilder
import space.kscience.dataforge.meta.toConfig
import space.kscience.dataforge.values.ValueType
import kotlin.reflect.KProperty1
@@ -15,7 +15,7 @@ import kotlin.reflect.typeOf
*/
public inline fun NodeDescriptorBuilder.value(
property: KProperty1,
- noinline block: ValueDescriptor.() -> Unit = {},
+ noinline block: ValueDescriptorBuilder.() -> Unit = {},
) {
when (typeOf()) {
typeOf(), typeOf(), typeOf(), typeOf(), typeOf(), typeOf() ->
@@ -54,7 +54,7 @@ public fun NodeDescriptor.copy(block: NodeDescriptorBuilder.() -> Unit = {}): No
public inline fun NodeDescriptorBuilder.scheme(
property: KProperty1,
spec: SchemeSpec,
- noinline block: NodeDescriptor.() -> Unit = {},
+ noinline block: NodeDescriptorBuilder.() -> Unit = {},
) {
spec.descriptor?.let { descriptor ->
item(property.name, descriptor.copy(block))
diff --git a/visionforge-core/src/commonTest/kotlin/space/kscience/visionforge/html/HtmlTagTest.kt b/visionforge-core/src/commonTest/kotlin/space/kscience/visionforge/html/HtmlTagTest.kt
index 5f35bd74..e50c13b3 100644
--- a/visionforge-core/src/commonTest/kotlin/space/kscience/visionforge/html/HtmlTagTest.kt
+++ b/visionforge-core/src/commonTest/kotlin/space/kscience/visionforge/html/HtmlTagTest.kt
@@ -2,13 +2,35 @@ package space.kscience.visionforge.html
import kotlinx.html.*
import kotlinx.html.stream.createHTML
+import space.kscience.dataforge.meta.Meta
import space.kscience.dataforge.meta.set
import space.kscience.dataforge.misc.DFExperimental
+import space.kscience.dataforge.names.Name
+import space.kscience.visionforge.Vision
import space.kscience.visionforge.VisionBase
import space.kscience.visionforge.configure
import space.kscience.visionforge.meta
import kotlin.test.Test
+typealias HtmlVisionRenderer = FlowContent.(name: Name, vision: Vision, meta: Meta) -> Unit
+
+fun FlowContent.renderVisionFragment(
+ renderer: DIV.(name: Name, vision: Vision, meta: Meta) -> Unit,
+ idPrefix: String? = null,
+ fragment: HtmlVisionFragment,
+): Map {
+ val visionMap = HashMap()
+ val consumer = object : VisionTagConsumer(consumer, idPrefix) {
+ override fun DIV.renderVision(name: Name, vision: Vision, outputMeta: Meta) {
+ visionMap[name] = vision
+ renderer(name, vision, outputMeta)
+ }
+ }
+ fragment(consumer)
+ return visionMap
+}
+
+
@DFExperimental
class HtmlTagTest {
@@ -46,15 +68,11 @@ class HtmlTagTest {
}
}
- val groupRenderer: HtmlVisionRenderer = { _, _, _ ->
- p { +"This is group" }
- }
-
@Test
fun testStringRender() {
println(
- createHTML().div {
+ createHTML().div{
renderVisionFragment(simpleVisionRenderer, fragment = fragment)
}
)
diff --git a/visionforge-core/src/jsMain/kotlin/space/kscience/visionforge/VisionClient.kt b/visionforge-core/src/jsMain/kotlin/space/kscience/visionforge/VisionClient.kt
index 47fed77b..8cd5dd09 100644
--- a/visionforge-core/src/jsMain/kotlin/space/kscience/visionforge/VisionClient.kt
+++ b/visionforge-core/src/jsMain/kotlin/space/kscience/visionforge/VisionClient.kt
@@ -7,6 +7,7 @@ import org.w3c.dom.url.URL
import space.kscience.dataforge.context.*
import space.kscience.dataforge.meta.Meta
import space.kscience.dataforge.meta.MetaSerializer
+import space.kscience.visionforge.html.RENDER_FUNCTION_NAME
import space.kscience.visionforge.html.VisionTagConsumer
import space.kscience.visionforge.html.VisionTagConsumer.Companion.OUTPUT_CONNECT_ATTRIBUTE
import space.kscience.visionforge.html.VisionTagConsumer.Companion.OUTPUT_ENDPOINT_ATTRIBUTE
@@ -221,7 +222,7 @@ public fun runVisionClient(contextBuilder: ContextBuilder.() -> Unit) {
//plugin(VisionClient)
}
val visionClient = context.fetch(VisionClient)
- window.asDynamic()["renderAllVisionsById"] = visionClient::renderAllVisionsById
+ window.asDynamic()[RENDER_FUNCTION_NAME] = visionClient::renderAllVisionsById
visionClient.renderAllVisions()
}
\ No newline at end of file
diff --git a/visionforge-gdml/src/commonMain/kotlin/space/kscience/visionforge/gdml/GdmlTransformer.kt b/visionforge-gdml/src/commonMain/kotlin/space/kscience/visionforge/gdml/GdmlTransformerEnv.kt
similarity index 84%
rename from visionforge-gdml/src/commonMain/kotlin/space/kscience/visionforge/gdml/GdmlTransformer.kt
rename to visionforge-gdml/src/commonMain/kotlin/space/kscience/visionforge/gdml/GdmlTransformerEnv.kt
index ac0e9e4b..c4a2364a 100644
--- a/visionforge-gdml/src/commonMain/kotlin/space/kscience/visionforge/gdml/GdmlTransformer.kt
+++ b/visionforge-gdml/src/commonMain/kotlin/space/kscience/visionforge/gdml/GdmlTransformerEnv.kt
@@ -25,8 +25,7 @@ private inline operator fun Number.times(d: Double) = toDouble() * d
@Suppress("NOTHING_TO_INLINE")
private inline operator fun Number.times(f: Float) = toFloat() * f
-public class GdmlTransformerSettings {
- public val random: Random = Random(222)
+public class GdmlTransformer {
public enum class Action {
ADD,
@@ -40,12 +39,70 @@ public class GdmlTransformerSettings {
public var solidAction: (GdmlSolid) -> Action = { Action.PROTOTYPE }
public var volumeAction: (GdmlGroup) -> Action = { Action.PROTOTYPE }
- public var paint: SolidMaterial.(material: GdmlMaterial) -> Unit = { _ ->
- color(random.nextInt(16777216))
+ internal val styleCache = HashMap()
+
+ public fun Solid.useStyle(name: String, builder: MetaBuilder.() -> Unit) {
+ styleCache.getOrPut(name.toName()) {
+ Meta(builder)
+ }
+ useStyle(name)
+ }
+
+ public fun Solid.opaque() {
+ useStyle("opaque") {
+ SolidMaterial.MATERIAL_OPACITY_KEY put 0.3
+ "edges.enabled" put true
+ }
+ }
+
+ /**
+ * Configure paint for given solid with given [GdmlMaterial]
+ */
+ public var configurePaint: SolidMaterial.(material: GdmlMaterial, solid: GdmlSolid) -> Unit =
+ { material, _ -> color(randomColor(material)) }
+ private set
+
+ public fun paint(block: SolidMaterial.(material: GdmlMaterial, solid: GdmlSolid) -> Unit) {
+ configurePaint = block
+ }
+
+ /**
+ * Configure given solid
+ */
+ public var configureSolid: Solid.(parent: GdmlVolume, solid: GdmlSolid, material: GdmlMaterial) -> Unit =
+ { parent, solid, material ->
+ val styleName = "materials.${material.name}"
+
+ if (parent.physVolumes.isNotEmpty()) opaque()
+
+ useStyle(styleName) {
+ val vfMaterial = SolidMaterial().apply {
+ configurePaint(material, solid)
+ }
+ MATERIAL_KEY put vfMaterial.toMeta()
+ "Gdml.material" put material.name
+ }
+ }
+ private set
+
+
+
+ public companion object {
+ private val random: Random = Random(222)
+
+ private val colorCache = HashMap()
+
+ /**
+ * Use random color and cache it based on the material. Meaning that colors are random, but always the same for the
+ * same material.
+ */
+ public fun randomColor(material: GdmlMaterial): Int {
+ return colorCache.getOrPut(material) { random.nextInt(16777216) }
+ }
}
}
-private class GdmlTransformer(val settings: GdmlTransformerSettings) {
+private class GdmlTransformerEnv(val settings: GdmlTransformer) {
//private val materialCache = HashMap()
/**
@@ -57,9 +114,13 @@ private class GdmlTransformer(val settings: GdmlTransformerSettings) {
setProperty("edges.enabled", false)
}
-
private val referenceStore = HashMap>()
+ fun Solid.configureSolid(root: Gdml, parent: GdmlVolume, solid: GdmlSolid) {
+ val material = parent.materialref.resolve(root) ?: GdmlElement(parent.materialref.ref)
+ settings.run { configureSolid(parent, solid, material) }
+ }
+
private fun proxySolid(root: Gdml, group: SolidGroup, solid: GdmlSolid, name: String): SolidReferenceGroup {
val templateName = solidsName + name
if (proto[templateName] == null) {
@@ -85,38 +146,6 @@ private class GdmlTransformer(val settings: GdmlTransformerSettings) {
return ref
}
- private val styleCache = HashMap()
-
- var solidConfiguration: Solid.(parent: GdmlVolume, solid: GdmlSolid) -> Unit = { parent, _ ->
- if (parent.physVolumes.isNotEmpty()) {
- useStyle("opaque") {
- SolidMaterial.MATERIAL_OPACITY_KEY put 0.3
- "edges.enabled" put true
- }
- }
- }
-
- fun Solid.useStyle(name: String, builder: MetaBuilder.() -> Unit) {
- styleCache.getOrPut(name.toName()) {
- Meta(builder)
- }
- useStyle(name)
- }
-
- fun configureSolid(root: Gdml, obj: Solid, parent: GdmlVolume, solid: GdmlSolid) {
- val material = parent.materialref.resolve(root) ?: GdmlElement(parent.materialref.ref)
-
- val styleName = "materials.${material.name}"
-
- obj.useStyle(styleName) {
- val vfMaterial = settings.run { SolidMaterial().apply { paint(material) } }
- MATERIAL_KEY put vfMaterial.toMeta()
- "Gdml.material" put material.name
- }
-
- obj.solidConfiguration(parent, solid)
- }
-
fun T.withPosition(
newPos: GdmlPosition? = null,
newRotation: GdmlRotation? = null,
@@ -314,13 +343,13 @@ private class GdmlTransformer(val settings: GdmlTransformerSettings) {
): Solid? {
require(name != "") { "Can't use empty solid name. Use null instead." }
return when (settings.solidAction(solid)) {
- GdmlTransformerSettings.Action.ADD -> {
+ GdmlTransformer.Action.ADD -> {
addSolid(root, solid, name)
}
- GdmlTransformerSettings.Action.PROTOTYPE -> {
+ GdmlTransformer.Action.PROTOTYPE -> {
proxySolid(root, this, solid, name ?: solid.name)
}
- GdmlTransformerSettings.Action.REJECT -> {
+ GdmlTransformer.Action.REJECT -> {
//ignore
null
}
@@ -339,21 +368,21 @@ private class GdmlTransformer(val settings: GdmlTransformerSettings) {
val solid = volume.solidref.resolve(root)
?: error("Solid with tag ${volume.solidref.ref} for volume ${volume.name} not defined")
addSolidWithCaching(root, solid, physVolume.name)?.apply {
- configureSolid(root, this, volume, solid)
+ configureSolid(root, volume, solid)
withPosition(root, physVolume)
}
return
}
when (settings.volumeAction(volume)) {
- GdmlTransformerSettings.Action.ADD -> {
+ GdmlTransformer.Action.ADD -> {
val group: SolidGroup = volume(root, volume)
this[physVolume.name] = group.withPosition(root, physVolume)
}
- GdmlTransformerSettings.Action.PROTOTYPE -> {
+ GdmlTransformer.Action.PROTOTYPE -> {
proxyVolume(root, this, physVolume, volume)
}
- GdmlTransformerSettings.Action.REJECT -> {
+ GdmlTransformer.Action.REJECT -> {
//ignore
}
}
@@ -379,7 +408,7 @@ private class GdmlTransformer(val settings: GdmlTransformerSettings) {
?: error("Solid with tag ${group.solidref.ref} for volume ${group.name} not defined")
addSolidWithCaching(root, solid, null)?.apply {
- configureSolid(root, this, group, solid)
+ this.configureSolid(root, group, solid)
}
when (val vol: GdmlPlacement? = group.placement) {
@@ -394,10 +423,10 @@ private class GdmlTransformer(val settings: GdmlTransformerSettings) {
}
private fun finalize(final: SolidGroup): SolidGroup {
- //final.prototypes = proto
- final.useStyle("gdml") {
+ val rootStyle by final.style("gdml") {
Solid.ROTATION_ORDER_KEY put RotationOrder.ZXY
}
+ final.useStyle(rootStyle)
//inline prototypes
// referenceStore.forEach { (protoName, list) ->
@@ -419,7 +448,7 @@ private class GdmlTransformer(val settings: GdmlTransformerSettings) {
set(token.asName(), item as? Solid)
}
}
- styleCache.forEach {
+ settings.styleCache.forEach {
final.styleSheet {
define(it.key.toString(), it.value)
}
@@ -432,15 +461,16 @@ private class GdmlTransformer(val settings: GdmlTransformerSettings) {
}
-public fun Gdml.toVision(block: GdmlTransformerSettings.() -> Unit = {}): SolidGroup {
- val context = GdmlTransformer(GdmlTransformerSettings().apply(block))
+public fun Gdml.toVision(block: GdmlTransformer.() -> Unit = {}): SolidGroup {
+ val settings = GdmlTransformer().apply(block)
+ val context = GdmlTransformerEnv(settings)
return context.transform(this)
}
/**
* Append Gdml node to the group
*/
-public fun SolidGroup.gdml(gdml: Gdml, key: String? = null, transformer: GdmlTransformerSettings.() -> Unit = {}) {
+public fun SolidGroup.gdml(gdml: Gdml, key: String? = null, transformer: GdmlTransformer.() -> Unit = {}) {
val visual = gdml.toVision(transformer)
//println(Visual3DPlugin.json.stringify(VisualGroup3D.serializer(), visual))
set(key, visual)
diff --git a/visionforge-gdml/src/jvmMain/kotlin/space/kscience/visionforge/gdml/gdmlJVM.kt b/visionforge-gdml/src/jvmMain/kotlin/space/kscience/visionforge/gdml/gdmlJVM.kt
index 310631ce..7bd17a5c 100644
--- a/visionforge-gdml/src/jvmMain/kotlin/space/kscience/visionforge/gdml/gdmlJVM.kt
+++ b/visionforge-gdml/src/jvmMain/kotlin/space/kscience/visionforge/gdml/gdmlJVM.kt
@@ -12,7 +12,7 @@ public fun SolidGroup.gdml(
file: Path,
key: String = "",
usePreprocessor: Boolean = false,
- transformer: GdmlTransformerSettings.() -> Unit = {},
+ transformer: GdmlTransformer.() -> Unit = {},
) {
val gdml = Gdml.decodeFromFile(file, usePreprocessor)
gdml(gdml, key, transformer)
diff --git a/visionforge-server/src/main/kotlin/space/kscience/visionforge/three/server/VisionServer.kt b/visionforge-server/src/main/kotlin/space/kscience/visionforge/three/server/VisionServer.kt
index c52a84a1..06c13bfe 100644
--- a/visionforge-server/src/main/kotlin/space/kscience/visionforge/three/server/VisionServer.kt
+++ b/visionforge-server/src/main/kotlin/space/kscience/visionforge/three/server/VisionServer.kt
@@ -89,7 +89,7 @@ public class VisionServer internal constructor(
script {
attributes["class"] = OUTPUT_DATA_CLASS
unsafe {
- +visionManager.encodeToString(vision)
+ +"\n${visionManager.encodeToString(vision)}\n"
}
}
}
diff --git a/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/specifications/Axes.kt b/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/specifications/Axes.kt
index 8b59a8b4..2f3e1645 100644
--- a/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/specifications/Axes.kt
+++ b/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/specifications/Axes.kt
@@ -18,9 +18,15 @@ public class Axes : Scheme() {
override val descriptor: NodeDescriptor by lazy {
NodeDescriptor {
- value(Axes::visible)
- value(Axes::size)
- value(Axes::width)
+ value(Axes::visible){
+ default(false)
+ }
+ value(Axes::size){
+ default(AXIS_SIZE)
+ }
+ value(Axes::width){
+ default(AXIS_WIDTH)
+ }
}
}
}
diff --git a/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/specifications/Camera.kt b/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/specifications/Camera.kt
index 00c36d50..b6209b54 100644
--- a/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/specifications/Camera.kt
+++ b/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/specifications/Camera.kt
@@ -30,12 +30,24 @@ public class Camera : Scheme() {
override val descriptor: NodeDescriptor by lazy {
NodeDescriptor {
- value(Camera::fov)
- value(Camera::nearClip)
- value(Camera::farClip)
- value(Camera::distance)
- value(Camera::azimuth)
- value(Camera::zenith)
+ value(Camera::fov){
+ default(FIELD_OF_VIEW)
+ }
+ value(Camera::nearClip){
+ default(NEAR_CLIP)
+ }
+ value(Camera::farClip){
+ default(FAR_CLIP)
+ }
+ value(Camera::distance){
+ default(INITIAL_DISTANCE)
+ }
+ value(Camera::azimuth){
+ default(INITIAL_AZIMUTH)
+ }
+ value(Camera::latitude){
+ default(INITIAL_LATITUDE)
+ }
}
}
}
diff --git a/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/specifications/Canvas3DOptions.kt b/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/specifications/Canvas3DOptions.kt
index bd3eebc3..aa7cb258 100644
--- a/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/specifications/Canvas3DOptions.kt
+++ b/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/specifications/Canvas3DOptions.kt
@@ -3,8 +3,11 @@ package space.kscience.visionforge.solid.specifications
import space.kscience.dataforge.meta.*
import space.kscience.dataforge.meta.descriptors.NodeDescriptor
import space.kscience.dataforge.names.Name
+import space.kscience.dataforge.values.ValueType
+import space.kscience.visionforge.hide
import space.kscience.visionforge.scheme
import space.kscience.visionforge.value
+import space.kscience.visionforge.widgetType
public class Canvas3DOptions : Scheme() {
public var axes: Axes by spec(Axes)
@@ -20,6 +23,8 @@ public class Canvas3DOptions : Scheme() {
public var maxWith: Number by number { maxSize }
public var maxHeight: Number by number { maxSize }
+ public var layers: List by numberList(0)
+
public var onSelect: ((Name?) -> Unit)? = null
@@ -28,14 +33,37 @@ public class Canvas3DOptions : Scheme() {
NodeDescriptor {
scheme(Canvas3DOptions::axes, Axes)
scheme(Canvas3DOptions::light, Light)
- scheme(Canvas3DOptions::camera, Camera)
- scheme(Canvas3DOptions::controls, Controls)
- value(Canvas3DOptions::minSize)
- value(Canvas3DOptions::minWith)
- value(Canvas3DOptions::minHeight)
- value(Canvas3DOptions::maxSize)
- value(Canvas3DOptions::maxWith)
- value(Canvas3DOptions::maxHeight)
+ scheme(Canvas3DOptions::camera, Camera) {
+ hide()
+ }
+ scheme(Canvas3DOptions::controls, Controls) {
+ hide()
+ }
+ value(Canvas3DOptions::minSize) {
+ hide()
+ }
+ value(Canvas3DOptions::minWith) {
+ hide()
+ }
+ value(Canvas3DOptions::minHeight) {
+ hide()
+ }
+ value(Canvas3DOptions::maxSize) {
+ hide()
+ }
+ value(Canvas3DOptions::maxWith) {
+ hide()
+ }
+ value(Canvas3DOptions::maxHeight) {
+ hide()
+ }
+ value(Canvas3DOptions::layers) {
+ type(ValueType.NUMBER)
+ multiple = true
+ default(listOf(0))
+ widgetType = "multiSelect"
+ allow(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
+ }
}
}
}
diff --git a/visionforge-threejs/src/main/kotlin/space/kscience/visionforge/solid/three/ThreeCanvas.kt b/visionforge-threejs/src/main/kotlin/space/kscience/visionforge/solid/three/ThreeCanvas.kt
index 034cf430..8d0e0d0d 100644
--- a/visionforge-threejs/src/main/kotlin/space/kscience/visionforge/solid/three/ThreeCanvas.kt
+++ b/visionforge-threejs/src/main/kotlin/space/kscience/visionforge/solid/three/ThreeCanvas.kt
@@ -52,7 +52,7 @@ public class ThreeCanvas(
private set
private val scene: Scene = Scene().apply {
- options.useProperty(Canvas3DOptions::axes){axesConfig->
+ options.useProperty(Canvas3DOptions::axes) { axesConfig ->
getObjectByName(AXES_NAME)?.let { remove(it) }
val axesObject = AxesHelper(axes.size.toInt()).apply { visible = axes.visible }
axesObject.name = AXES_NAME
@@ -60,7 +60,7 @@ public class ThreeCanvas(
}
//Set up light
- options.useProperty(Canvas3DOptions::light){lightConfig->
+ options.useProperty(Canvas3DOptions::light) { lightConfig ->
//remove old light if present
getObjectByName(LIGHT_NAME)?.let { remove(it) }
//add new light
@@ -70,8 +70,29 @@ public class ThreeCanvas(
}
}
- public var camera: PerspectiveCamera = buildCamera(options.camera)
- private set
+
+ private fun buildCamera(spec: Camera) = PerspectiveCamera(
+ spec.fov,
+ 1.0,
+ spec.nearClip,
+ spec.farClip
+ ).apply {
+ translateX(spec.distance * sin(spec.zenith) * sin(spec.azimuth))
+ translateY(spec.distance * cos(spec.zenith))
+ translateZ(spec.distance * sin(spec.zenith) * cos(spec.azimuth))
+ options.useProperty(Canvas3DOptions::layers) { selectedLayers ->
+ (0..31).forEach {
+ if (it in selectedLayers) {
+ this@apply.layers.enable(it)
+ } else{
+ this@apply.layers.disable(it)
+ }
+ }
+ }
+ }
+
+
+ public val camera: PerspectiveCamera = buildCamera(options.camera)
private var picked: Object3D? = null
@@ -127,7 +148,6 @@ public class ThreeCanvas(
mousePosition.x = ((event.clientX - rect.left) / canvas.clientWidth) * 2 - 1
mousePosition.y = -((event.clientY - rect.top) / canvas.clientHeight) * 2 + 1
}
- event.preventDefault()
}, false)
canvas.onresize = {
@@ -185,17 +205,6 @@ public class ThreeCanvas(
private fun buildLight(spec: Light?): info.laht.threekt.lights.Light = AmbientLight(0x404040)
- private fun buildCamera(spec: Camera) = PerspectiveCamera(
- spec.fov,
- 1.0,
- spec.nearClip,
- spec.farClip
- ).apply {
- translateX(spec.distance * sin(spec.zenith) * sin(spec.azimuth))
- translateY(spec.distance * cos(spec.zenith))
- translateZ(spec.distance * sin(spec.zenith) * cos(spec.azimuth))
- }
-
private fun addControls(element: Node, controls: Controls) {
when (controls["type"].string) {
"trackball" -> TrackballControls(camera, element)