Add multi-select value chooser for layers
This commit is contained in:
parent
2798439582
commit
faf3fa8512
@ -5,7 +5,6 @@
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>Three js demo for particle physics</title>
|
||||
<script type="text/javascript" src="gdml.js"></script>
|
||||
<link rel="stylesheet" href="css/custom-bootstrap.css">
|
||||
<link rel="stylesheet" href="css/fileDrop.css">
|
||||
</head>
|
||||
<body class="application">
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -10,9 +10,7 @@ fun main() {
|
||||
plugin(Solids)
|
||||
}
|
||||
|
||||
context.makeVisionFile{
|
||||
vision("canvas") {
|
||||
GdmlShowCase.babyIaxo().toVision()
|
||||
}
|
||||
context.makeVisionFile {
|
||||
vision("canvas") { GdmlShowCase.babyIaxo().toVision() }
|
||||
}
|
||||
}
|
@ -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<Gdml> { gdmlModel ->
|
||||
val fragment = HtmlVisionFragment {
|
||||
vision(gdmlModel.toVision())
|
||||
}
|
||||
HTML(produceHtmlVisionString(fragment))
|
||||
}
|
||||
|
||||
render<Vision> { vision ->
|
||||
val fragment = HtmlVisionFragment {
|
||||
vision(vision)
|
||||
HTML(produceHtmlVisionString { vision(vision) })
|
||||
}
|
||||
|
||||
HTML(produceHtmlVisionString(fragment))
|
||||
render<Gdml> { gdmlModel ->
|
||||
HTML(produceHtmlVisionString { vision(gdmlModel.toVision()) })
|
||||
}
|
||||
|
||||
render<Page> { page ->
|
||||
|
@ -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"))
|
||||
}
|
@ -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<ValueChooserProps> =
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -152,6 +152,7 @@ public val ValueChooser: FunctionalComponent<ValueChooserProps> = 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)
|
||||
|
@ -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<Any?, StyleReference> =
|
||||
ReadOnlyProperty { _, property ->
|
||||
val styleName = property.name
|
||||
public fun VisionGroup.style(
|
||||
styleKey: String? = null,
|
||||
builder: MetaBuilder.() -> Unit,
|
||||
): ReadOnlyProperty<Any?, StyleReference> = ReadOnlyProperty { _, property ->
|
||||
val styleName = styleKey ?: property.name
|
||||
styleSheet.define(styleName, Meta(builder))
|
||||
StyleReference(this, styleName)
|
||||
}
|
||||
}
|
||||
|
||||
@VisionBuilder
|
||||
public fun <T : Scheme> VisionGroup.style(
|
||||
spec: Specification<T>,
|
||||
styleKey: String? = null,
|
||||
builder: T.() -> Unit,
|
||||
): ReadOnlyProperty<Any?, StyleReference> = ReadOnlyProperty { _, property ->
|
||||
val styleName = styleKey ?: property.name
|
||||
styleSheet.define(styleName, spec(builder).toMeta())
|
||||
StyleReference(this, styleName)
|
||||
}
|
@ -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<Name, Vision> = 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<Name, Vision> {
|
||||
val visionMap = HashMap<Name, Vision>()
|
||||
val consumer = object : VisionTagConsumer<Any?>(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
|
||||
}
|
@ -66,7 +66,9 @@ public abstract class VisionTagConsumer<R>(
|
||||
}
|
||||
}
|
||||
}
|
||||
vision?.let { renderVision(name, it, outputMeta) }
|
||||
vision?.let {
|
||||
renderVision(name, it, outputMeta)
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(DFExperimental::class)
|
||||
|
@ -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 <S : Scheme, reified T> NodeDescriptorBuilder.value(
|
||||
property: KProperty1<S, T>,
|
||||
noinline block: ValueDescriptor.() -> Unit = {},
|
||||
noinline block: ValueDescriptorBuilder.() -> Unit = {},
|
||||
) {
|
||||
when (typeOf<T>()) {
|
||||
typeOf<Number>(), typeOf<Int>(), typeOf<Double>(), typeOf<Short>(), typeOf<Long>(), typeOf<Float>() ->
|
||||
@ -54,7 +54,7 @@ public fun NodeDescriptor.copy(block: NodeDescriptorBuilder.() -> Unit = {}): No
|
||||
public inline fun <S : Scheme, reified T : Scheme> NodeDescriptorBuilder.scheme(
|
||||
property: KProperty1<S, T>,
|
||||
spec: SchemeSpec<T>,
|
||||
noinline block: NodeDescriptor.() -> Unit = {},
|
||||
noinline block: NodeDescriptorBuilder.() -> Unit = {},
|
||||
) {
|
||||
spec.descriptor?.let { descriptor ->
|
||||
item(property.name, descriptor.copy(block))
|
||||
|
@ -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<Name, Vision> {
|
||||
val visionMap = HashMap<Name, Vision>()
|
||||
val consumer = object : VisionTagConsumer<Any?>(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)
|
||||
}
|
||||
)
|
||||
|
@ -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()
|
||||
}
|
@ -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<Name, Meta>()
|
||||
|
||||
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<GdmlMaterial, Int>()
|
||||
|
||||
/**
|
||||
* 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<GdmlMaterial, Meta>()
|
||||
|
||||
/**
|
||||
@ -57,9 +114,13 @@ private class GdmlTransformer(val settings: GdmlTransformerSettings) {
|
||||
setProperty("edges.enabled", false)
|
||||
}
|
||||
|
||||
|
||||
private val referenceStore = HashMap<Name, MutableList<SolidReferenceGroup>>()
|
||||
|
||||
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<Name, Meta>()
|
||||
|
||||
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 : Solid> 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)
|
@ -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)
|
||||
|
@ -89,7 +89,7 @@ public class VisionServer internal constructor(
|
||||
script {
|
||||
attributes["class"] = OUTPUT_DATA_CLASS
|
||||
unsafe {
|
||||
+visionManager.encodeToString(vision)
|
||||
+"\n${visionManager.encodeToString(vision)}\n"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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<Number> 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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user