forked from kscience/visionforge
Fix CME in solid children clearing. Add documentation. Splic client
This commit is contained in:
parent
cf6d73305b
commit
9c1246fb26
@ -8,7 +8,7 @@ import space.kscience.plotly.models.Trace
|
||||
import space.kscience.plotly.scatter
|
||||
import space.kscience.visionforge.Application
|
||||
import space.kscience.visionforge.Colors
|
||||
import space.kscience.visionforge.VisionClient
|
||||
import space.kscience.visionforge.JsVisionClient
|
||||
import space.kscience.visionforge.plotly.PlotlyPlugin
|
||||
import space.kscience.visionforge.react.createRoot
|
||||
import space.kscience.visionforge.react.render
|
||||
@ -34,7 +34,7 @@ private class JsPlaygroundApp : Application {
|
||||
|
||||
val playgroundContext = Context {
|
||||
plugin(ThreeWithControlsPlugin)
|
||||
plugin(VisionClient)
|
||||
plugin(JsVisionClient)
|
||||
plugin(PlotlyPlugin)
|
||||
}
|
||||
|
||||
|
@ -13,6 +13,7 @@ kscience {
|
||||
useKtor()
|
||||
fullStack(
|
||||
"muon-monitor.js",
|
||||
development = true,
|
||||
jvmConfig = { withJava() },
|
||||
jsConfig = { useCommonJs() }
|
||||
) {
|
||||
|
@ -3,6 +3,7 @@ package ru.mipt.npm.muon.monitor
|
||||
import ru.mipt.npm.muon.monitor.Monitor.CENTRAL_LAYER_Z
|
||||
import ru.mipt.npm.muon.monitor.Monitor.LOWER_LAYER_Z
|
||||
import ru.mipt.npm.muon.monitor.Monitor.UPPER_LAYER_Z
|
||||
import space.kscience.dataforge.names.asName
|
||||
import space.kscience.visionforge.MutableVisionContainer
|
||||
import space.kscience.visionforge.VisionManager
|
||||
import space.kscience.visionforge.setAsRoot
|
||||
@ -34,7 +35,7 @@ class Model(val manager: VisionManager) {
|
||||
}
|
||||
}
|
||||
|
||||
var tracks: SolidGroup
|
||||
val tracks: SolidGroup = SolidGroup()
|
||||
|
||||
val root: SolidGroup = SolidGroup().apply {
|
||||
setAsRoot(this@Model.manager)
|
||||
@ -59,7 +60,8 @@ class Model(val manager: VisionManager) {
|
||||
detector(it)
|
||||
}
|
||||
}
|
||||
tracks = solidGroup("tracks")
|
||||
|
||||
setChild("tracks".asName(), tracks)
|
||||
}
|
||||
|
||||
private fun highlight(pixel: String) {
|
||||
|
@ -0,0 +1,42 @@
|
||||
package space.kscience.visionforge
|
||||
|
||||
import kotlinx.coroutines.launch
|
||||
import space.kscience.dataforge.context.Plugin
|
||||
import space.kscience.dataforge.meta.Meta
|
||||
import space.kscience.dataforge.meta.MetaRepr
|
||||
import space.kscience.dataforge.names.Name
|
||||
import space.kscience.dataforge.names.parseAsName
|
||||
|
||||
/**
|
||||
* A feedback client that communicates with a server and provides ability to propagate events and changes back to the model
|
||||
*/
|
||||
public interface VisionClient: Plugin {
|
||||
public val visionManager: VisionManager
|
||||
|
||||
public suspend fun sendEvent(event: VisionEvent)
|
||||
|
||||
public fun notifyPropertyChanged(visionName: Name, propertyName: Name, item: Meta?)
|
||||
}
|
||||
|
||||
|
||||
public fun VisionClient.notifyPropertyChanged(visionName: Name, propertyName: String, item: Meta?) {
|
||||
notifyPropertyChanged(visionName, propertyName.parseAsName(true), item)
|
||||
}
|
||||
|
||||
public fun VisionClient.notifyPropertyChanged(visionName: Name, propertyName: String, item: Number) {
|
||||
notifyPropertyChanged(visionName, propertyName.parseAsName(true), Meta(item))
|
||||
}
|
||||
|
||||
public fun VisionClient.notifyPropertyChanged(visionName: Name, propertyName: String, item: String) {
|
||||
notifyPropertyChanged(visionName, propertyName.parseAsName(true), Meta(item))
|
||||
}
|
||||
|
||||
public fun VisionClient.notifyPropertyChanged(visionName: Name, propertyName: String, item: Boolean) {
|
||||
notifyPropertyChanged(visionName, propertyName.parseAsName(true), Meta(item))
|
||||
}
|
||||
|
||||
public fun VisionClient.sendEvent(visionName: Name, event: MetaRepr): Unit {
|
||||
context.launch {
|
||||
sendEvent(VisionMetaEvent(visionName, event.toMeta()))
|
||||
}
|
||||
}
|
@ -187,30 +187,10 @@ internal abstract class VisionChildrenImpl(
|
||||
}
|
||||
|
||||
override fun clear() {
|
||||
items?.forEach { set(it.key, null) }
|
||||
// if (!items.isNullOrEmpty()) {
|
||||
// updateJobs.values.forEach {
|
||||
// it.cancel()
|
||||
// }
|
||||
// updateJobs.clear()
|
||||
// items?.clear()
|
||||
// }
|
||||
items?.clear()
|
||||
updateJobs.values.forEach { it.cancel() }
|
||||
updateJobs.clear()
|
||||
onChange(Name.EMPTY)
|
||||
}
|
||||
}
|
||||
//
|
||||
//internal object VisionChildrenContainerSerializer : KSerializer<MutableVisionChildren> {
|
||||
// private val mapSerializer = serializer<Map<NameToken, Vision>>()
|
||||
//
|
||||
// override val descriptor: SerialDescriptor = mapSerializer.descriptor
|
||||
//
|
||||
// override fun deserialize(decoder: Decoder): MutableVisionChildren {
|
||||
// val map = decoder.decodeSerializableValue(mapSerializer)
|
||||
// return VisionChildrenImpl(map)
|
||||
// }
|
||||
//
|
||||
// override fun serialize(encoder: Encoder, value: MutableVisionChildren) {
|
||||
// val map = value.keys.associateWith { value[it]!! }
|
||||
// encoder.encodeSerializableValue(mapSerializer, map)
|
||||
// }
|
||||
//
|
||||
//}
|
||||
|
||||
|
@ -3,6 +3,8 @@ package space.kscience.visionforge
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
import space.kscience.dataforge.meta.Meta
|
||||
import space.kscience.dataforge.meta.MutableMeta
|
||||
import space.kscience.dataforge.meta.set
|
||||
import space.kscience.dataforge.names.Name
|
||||
|
||||
/**
|
||||
@ -11,6 +13,10 @@ import space.kscience.dataforge.names.Name
|
||||
@Serializable
|
||||
public sealed interface VisionEvent{
|
||||
public val targetName: Name
|
||||
|
||||
public companion object{
|
||||
public val CLICK_EVENT_KEY: Name get() = Name.of("events", "click", "payload")
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -23,3 +29,12 @@ public class VisionMetaEvent(override val targetName: Name, public val meta: Met
|
||||
@Serializable
|
||||
@SerialName("change")
|
||||
public class VisionChangeEvent(override val targetName: Name, public val change: VisionChange) : VisionEvent
|
||||
|
||||
public val Vision.Companion.CLICK_EVENT_KEY: Name get() = Name.of("events", "click", "payload")
|
||||
|
||||
/**
|
||||
* Set the payload to be sent to server on click
|
||||
*/
|
||||
public fun Vision.onClickPayload(payloadBuilder: MutableMeta.() -> Unit){
|
||||
properties[VisionEvent.CLICK_EVENT_KEY] = Meta(payloadBuilder)
|
||||
}
|
@ -15,7 +15,10 @@ import kotlinx.coroutines.sync.withLock
|
||||
import org.w3c.dom.*
|
||||
import org.w3c.dom.url.URL
|
||||
import space.kscience.dataforge.context.*
|
||||
import space.kscience.dataforge.meta.*
|
||||
import space.kscience.dataforge.meta.Meta
|
||||
import space.kscience.dataforge.meta.MetaSerializer
|
||||
import space.kscience.dataforge.meta.get
|
||||
import space.kscience.dataforge.meta.int
|
||||
import space.kscience.dataforge.names.Name
|
||||
import space.kscience.dataforge.names.parseAsName
|
||||
import space.kscience.visionforge.html.VisionTagConsumer
|
||||
@ -29,9 +32,9 @@ import kotlin.time.Duration.Companion.milliseconds
|
||||
/**
|
||||
* A Kotlin-browser plugin that renders visions based on provided renderers and governs communication with the server.
|
||||
*/
|
||||
public class VisionClient : AbstractPlugin() {
|
||||
public class JsVisionClient : AbstractPlugin(), VisionClient {
|
||||
override val tag: PluginTag get() = Companion.tag
|
||||
private val visionManager: VisionManager by require(VisionManager)
|
||||
override val visionManager: VisionManager by require(VisionManager)
|
||||
|
||||
/**
|
||||
* Up-going tree traversal in search for endpoint attribute. If element is null, return window URL
|
||||
@ -69,7 +72,7 @@ public class VisionClient : AbstractPlugin() {
|
||||
/**
|
||||
* Communicate vision property changed from rendering engine to model
|
||||
*/
|
||||
public fun notifyPropertyChanged(visionName: Name, propertyName: Name, item: Meta?) {
|
||||
override fun notifyPropertyChanged(visionName: Name, propertyName: Name, item: Meta?) {
|
||||
context.launch {
|
||||
mutex.withLock {
|
||||
changeCollector.propertyChanged(visionName, propertyName, item)
|
||||
@ -85,7 +88,7 @@ public class VisionClient : AbstractPlugin() {
|
||||
/**
|
||||
* Send a custom feedback event
|
||||
*/
|
||||
public suspend fun sendEvent(event: VisionEvent) {
|
||||
override suspend fun sendEvent(event: VisionEvent) {
|
||||
eventCollector.emit(event)
|
||||
}
|
||||
|
||||
@ -252,37 +255,15 @@ public class VisionClient : AbstractPlugin() {
|
||||
textVisionRenderer(this),
|
||||
formVisionRenderer(this)
|
||||
).associateByName()
|
||||
} else super.content(target)
|
||||
} else super<AbstractPlugin>.content(target)
|
||||
|
||||
public companion object : PluginFactory<VisionClient> {
|
||||
override fun build(context: Context, meta: Meta): VisionClient = VisionClient()
|
||||
public companion object : PluginFactory<JsVisionClient> {
|
||||
override fun build(context: Context, meta: Meta): JsVisionClient = JsVisionClient()
|
||||
|
||||
override val tag: PluginTag = PluginTag(name = "vision.client.js", group = PluginTag.DATAFORGE_GROUP)
|
||||
}
|
||||
}
|
||||
|
||||
public fun VisionClient.notifyPropertyChanged(visionName: Name, propertyName: String, item: Meta?) {
|
||||
notifyPropertyChanged(visionName, propertyName.parseAsName(true), item)
|
||||
}
|
||||
|
||||
public fun VisionClient.notifyPropertyChanged(visionName: Name, propertyName: String, item: Number) {
|
||||
notifyPropertyChanged(visionName, propertyName.parseAsName(true), Meta(item))
|
||||
}
|
||||
|
||||
public fun VisionClient.notifyPropertyChanged(visionName: Name, propertyName: String, item: String) {
|
||||
notifyPropertyChanged(visionName, propertyName.parseAsName(true), Meta(item))
|
||||
}
|
||||
|
||||
public fun VisionClient.notifyPropertyChanged(visionName: Name, propertyName: String, item: Boolean) {
|
||||
notifyPropertyChanged(visionName, propertyName.parseAsName(true), Meta(item))
|
||||
}
|
||||
|
||||
public fun VisionClient.sendEvent(visionName: Name, event: MetaRepr): Unit {
|
||||
context.launch {
|
||||
sendEvent(VisionMetaEvent(visionName, event.toMeta()))
|
||||
}
|
||||
}
|
||||
|
||||
private fun whenDocumentLoaded(block: Document.() -> Unit): Unit {
|
||||
if (document.body != null) {
|
||||
block(document)
|
||||
@ -294,7 +275,7 @@ private fun whenDocumentLoaded(block: Document.() -> Unit): Unit {
|
||||
/**
|
||||
* Fetch and render visions for all elements with [VisionTagConsumer.OUTPUT_CLASS] class inside given [element].
|
||||
*/
|
||||
public fun VisionClient.renderAllVisionsIn(element: Element) {
|
||||
public fun JsVisionClient.renderAllVisionsIn(element: Element) {
|
||||
val elements = element.getElementsByClassName(VisionTagConsumer.OUTPUT_CLASS)
|
||||
logger.info { "Finished search for outputs. Found ${elements.length} items" }
|
||||
elements.asList().forEach { child ->
|
||||
@ -305,7 +286,7 @@ public fun VisionClient.renderAllVisionsIn(element: Element) {
|
||||
/**
|
||||
* Render all visions in an element with a given [id]
|
||||
*/
|
||||
public fun VisionClient.renderAllVisionsById(document: Document, id: String): Unit {
|
||||
public fun JsVisionClient.renderAllVisionsById(document: Document, id: String): Unit {
|
||||
val element = document.getElementById(id)
|
||||
if (element != null) {
|
||||
renderAllVisionsIn(element)
|
||||
@ -318,13 +299,13 @@ public fun VisionClient.renderAllVisionsById(document: Document, id: String): Un
|
||||
/**
|
||||
* Fetch visions from the server for all elements with [VisionTagConsumer.OUTPUT_CLASS] class in the document body
|
||||
*/
|
||||
public fun VisionClient.renderAllVisions(): Unit = whenDocumentLoaded {
|
||||
public fun JsVisionClient.renderAllVisions(): Unit = whenDocumentLoaded {
|
||||
val element = body ?: error("Document does not have a body")
|
||||
renderAllVisionsIn(element)
|
||||
}
|
||||
|
||||
public class VisionClientApplication(public val context: Context) : Application {
|
||||
private val client = context.request(VisionClient)
|
||||
private val client = context.request(JsVisionClient)
|
||||
|
||||
override fun start(document: Document, state: Map<String, Any>) {
|
||||
context.logger.info {
|
||||
@ -348,7 +329,7 @@ public fun runVisionClient(contextBuilder: ContextBuilder.() -> Unit) {
|
||||
Global.logger.info { "Starting VisionForge context" }
|
||||
|
||||
val context = Context("VisionForge") {
|
||||
plugin(VisionClient)
|
||||
plugin(JsVisionClient)
|
||||
contextBuilder()
|
||||
}
|
||||
|
@ -20,7 +20,7 @@ import space.kscience.visionforge.html.VisionOfNumberField
|
||||
import space.kscience.visionforge.html.VisionOfTextField
|
||||
|
||||
internal fun textVisionRenderer(
|
||||
client: VisionClient,
|
||||
client: JsVisionClient,
|
||||
): ElementVisionRenderer = ElementVisionRenderer<VisionOfTextField> { name, vision, _ ->
|
||||
val fieldName = vision.name ?: "input[${vision.hashCode().toUInt()}]"
|
||||
vision.label?.let {
|
||||
@ -42,7 +42,7 @@ internal fun textVisionRenderer(
|
||||
}
|
||||
|
||||
internal fun numberVisionRenderer(
|
||||
client: VisionClient,
|
||||
client: JsVisionClient,
|
||||
): ElementVisionRenderer = ElementVisionRenderer<VisionOfNumberField> { name, vision, _ ->
|
||||
val fieldName = vision.name ?: "input[${vision.hashCode().toUInt()}]"
|
||||
vision.label?.let {
|
||||
@ -87,7 +87,7 @@ internal fun FormData.toMeta(): Meta {
|
||||
}
|
||||
|
||||
internal fun formVisionRenderer(
|
||||
client: VisionClient,
|
||||
client: JsVisionClient,
|
||||
): ElementVisionRenderer = ElementVisionRenderer<VisionOfHtmlForm> { name, vision, _ ->
|
||||
|
||||
val form = document.getElementById(vision.formId) as? HTMLFormElement
|
||||
|
@ -8,14 +8,14 @@ import space.kscience.dataforge.context.Context
|
||||
import space.kscience.dataforge.context.PluginFactory
|
||||
import space.kscience.dataforge.context.PluginTag
|
||||
import space.kscience.dataforge.meta.Meta
|
||||
import space.kscience.visionforge.VisionClient
|
||||
import space.kscience.visionforge.JsVisionClient
|
||||
import space.kscience.visionforge.renderAllVisions
|
||||
import space.kscience.visionforge.renderAllVisionsById
|
||||
import space.kscience.visionforge.renderAllVisionsIn
|
||||
|
||||
@JsExport
|
||||
public class VFNotebookClient : AbstractPlugin() {
|
||||
private val client by require(VisionClient)
|
||||
private val client by require(JsVisionClient)
|
||||
|
||||
public fun renderAllVisionsIn(element: Element) {
|
||||
client.renderAllVisionsIn(element)
|
||||
|
@ -18,7 +18,7 @@ import space.kscience.visionforge.markup.VisionOfMarkup.Companion.COMMONMARK_FOR
|
||||
import space.kscience.visionforge.markup.VisionOfMarkup.Companion.GFM_FORMAT
|
||||
|
||||
public actual class MarkupPlugin : VisionPlugin(), ElementVisionRenderer {
|
||||
public val visionClient: VisionClient by require(VisionClient)
|
||||
public val visionClient: JsVisionClient by require(JsVisionClient)
|
||||
override val tag: PluginTag get() = Companion.tag
|
||||
override val visionSerializersModule: SerializersModule get() = markupSerializersModule
|
||||
|
||||
|
@ -11,12 +11,12 @@ import space.kscience.dataforge.names.asName
|
||||
import space.kscience.plotly.PlotlyConfig
|
||||
import space.kscience.plotly.plot
|
||||
import space.kscience.visionforge.ElementVisionRenderer
|
||||
import space.kscience.visionforge.JsVisionClient
|
||||
import space.kscience.visionforge.Vision
|
||||
import space.kscience.visionforge.VisionClient
|
||||
import space.kscience.visionforge.VisionPlugin
|
||||
|
||||
public actual class PlotlyPlugin : VisionPlugin(), ElementVisionRenderer {
|
||||
public val visionClient: VisionClient by require(VisionClient)
|
||||
public val visionClient: JsVisionClient by require(JsVisionClient)
|
||||
|
||||
override val tag: PluginTag get() = Companion.tag
|
||||
|
||||
|
@ -15,6 +15,9 @@ public enum class CompositeType {
|
||||
SUBTRACT
|
||||
}
|
||||
|
||||
/**
|
||||
* A CSG-based composite solid
|
||||
*/
|
||||
@Serializable
|
||||
@SerialName("solid.composite")
|
||||
public class Composite(
|
||||
|
@ -5,6 +5,9 @@ import kotlinx.serialization.Serializable
|
||||
import space.kscience.visionforge.MutableVisionContainer
|
||||
import space.kscience.visionforge.setChild
|
||||
|
||||
/**
|
||||
* A convex hull shape
|
||||
*/
|
||||
@Serializable
|
||||
@SerialName("solid.convex")
|
||||
public class Convex(public val points: List<Float32Vector3D>) : SolidBase<Convex>()
|
||||
|
@ -12,7 +12,7 @@ import space.kscience.dataforge.names.asName
|
||||
import space.kscience.visionforge.*
|
||||
|
||||
@Serializable
|
||||
public abstract class LightSource : SolidBase<LightSource>() {
|
||||
public abstract class LightSource : MiscSolid() {
|
||||
override val descriptor: MetaDescriptor get() = LightSource.descriptor
|
||||
|
||||
public val color: ColorAccessor by colorProperty(SolidMaterial.COLOR_KEY)
|
||||
|
@ -6,13 +6,19 @@ import space.kscience.visionforge.MutableVisionContainer
|
||||
import space.kscience.visionforge.VisionBuilder
|
||||
import space.kscience.visionforge.setChild
|
||||
|
||||
/**
|
||||
* Utility solids
|
||||
*/
|
||||
public abstract class MiscSolid: SolidBase<MiscSolid>()
|
||||
|
||||
/**
|
||||
* X-Y-Z axes
|
||||
*/
|
||||
@Serializable
|
||||
@SerialName("solid.axes")
|
||||
public class AxesSolid(public val size: Double): MiscSolid(){
|
||||
public companion object{
|
||||
public const val AXES_NAME: String = "@xes"
|
||||
public const val AXES_NAME: String = "@axes"
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -7,6 +7,9 @@ import kotlin.math.sin
|
||||
|
||||
public typealias Shape2D = List<Float32Vector2D>
|
||||
|
||||
/**
|
||||
* A builder for 2D shapes
|
||||
*/
|
||||
@Serializable
|
||||
public class Shape2DBuilder(private val points: ArrayList<Float32Vector2D> = ArrayList()) {
|
||||
|
||||
|
@ -152,7 +152,10 @@ public var Vision.ignore: Boolean?
|
||||
// get() = getProperty(SELECTED_KEY).boolean
|
||||
// set(value) = setProperty(SELECTED_KEY, value)
|
||||
|
||||
internal fun float(name: Name, default: Number): ReadWriteProperty<Solid, Number> =
|
||||
/**
|
||||
*A [Float] solid property delegate
|
||||
*/
|
||||
internal fun float32(name: Name, default: Number): ReadWriteProperty<Solid, Number> =
|
||||
object : ReadWriteProperty<Solid, Number> {
|
||||
override fun getValue(thisRef: Solid, property: KProperty<*>): Number {
|
||||
return thisRef.properties.getValue(name)?.number ?: default
|
||||
@ -163,7 +166,10 @@ internal fun float(name: Name, default: Number): ReadWriteProperty<Solid, Number
|
||||
}
|
||||
}
|
||||
|
||||
internal fun point(
|
||||
/**
|
||||
* A [Float32Vector3D] solid property delegate
|
||||
*/
|
||||
internal fun float32Vector(
|
||||
name: Name,
|
||||
defaultX: Float,
|
||||
defaultY: Float = defaultX,
|
||||
@ -193,17 +199,17 @@ internal fun point(
|
||||
}
|
||||
}
|
||||
|
||||
public var Solid.position: Float32Vector3D? by point(POSITION_KEY, 0f)
|
||||
public var Solid.rotation: Float32Vector3D? by point(ROTATION_KEY, 0f)
|
||||
public var Solid.scale: Float32Vector3D? by point(SCALE_KEY, 1f)
|
||||
public var Solid.position: Float32Vector3D? by float32Vector(POSITION_KEY, 0f)
|
||||
public var Solid.rotation: Float32Vector3D? by float32Vector(ROTATION_KEY, 0f)
|
||||
public var Solid.scale: Float32Vector3D? by float32Vector(SCALE_KEY, 1f)
|
||||
|
||||
public var Solid.x: Number by float(X_POSITION_KEY, 0f)
|
||||
public var Solid.y: Number by float(Y_POSITION_KEY, 0f)
|
||||
public var Solid.z: Number by float(Z_POSITION_KEY, 0f)
|
||||
public var Solid.x: Number by float32(X_POSITION_KEY, 0f)
|
||||
public var Solid.y: Number by float32(Y_POSITION_KEY, 0f)
|
||||
public var Solid.z: Number by float32(Z_POSITION_KEY, 0f)
|
||||
|
||||
public var Solid.rotationX: Number by float(X_ROTATION_KEY, 0f)
|
||||
public var Solid.rotationY: Number by float(Y_ROTATION_KEY, 0f)
|
||||
public var Solid.rotationZ: Number by float(Z_ROTATION_KEY, 0f)
|
||||
public var Solid.rotationX: Number by float32(X_ROTATION_KEY, 0f)
|
||||
public var Solid.rotationY: Number by float32(Y_ROTATION_KEY, 0f)
|
||||
public var Solid.rotationZ: Number by float32(Z_ROTATION_KEY, 0f)
|
||||
|
||||
/**
|
||||
* Raw quaternion value defined in properties
|
||||
@ -241,9 +247,9 @@ public var Solid.quaternion: Quaternion
|
||||
quaternionOrNull = value
|
||||
}
|
||||
|
||||
public var Solid.scaleX: Number by float(X_SCALE_KEY, 1f)
|
||||
public var Solid.scaleY: Number by float(Y_SCALE_KEY, 1f)
|
||||
public var Solid.scaleZ: Number by float(Z_SCALE_KEY, 1f)
|
||||
public var Solid.scaleX: Number by float32(X_SCALE_KEY, 1f)
|
||||
public var Solid.scaleY: Number by float32(Y_SCALE_KEY, 1f)
|
||||
public var Solid.scaleZ: Number by float32(Z_SCALE_KEY, 1f)
|
||||
|
||||
/**
|
||||
* Add rotation with given [angle] relative to given [axis]
|
||||
|
@ -5,6 +5,9 @@ import kotlinx.serialization.Serializable
|
||||
import space.kscience.dataforge.meta.descriptors.MetaDescriptor
|
||||
import space.kscience.visionforge.AbstractVision
|
||||
|
||||
/**
|
||||
* An abstract solid that is both [Solid] and [AbstractVision]
|
||||
*/
|
||||
@Serializable
|
||||
@SerialName("solid")
|
||||
public open class SolidBase<T : Solid> : AbstractVision(), Solid {
|
||||
|
@ -12,6 +12,9 @@ import space.kscience.visionforge.solid.SolidMaterial.Companion.MATERIAL_COLOR_K
|
||||
import space.kscience.visionforge.solid.SolidMaterial.Companion.MATERIAL_KEY
|
||||
import space.kscience.visionforge.solid.SolidMaterial.Companion.MATERIAL_OPACITY_KEY
|
||||
|
||||
/**
|
||||
* A scheme for vision material
|
||||
*/
|
||||
@VisionBuilder
|
||||
public class SolidMaterial : Scheme() {
|
||||
|
||||
|
@ -21,6 +21,7 @@ import space.kscience.visionforge.solid.SolidReference.Companion.REFERENCE_CHILD
|
||||
* Get a vision prototype if it is a [SolidReference] or vision itself if it is not.
|
||||
* Unref is recursive, so it always returns a non-reference.
|
||||
*/
|
||||
@Suppress("RecursivePropertyAccessor")
|
||||
public val Vision.prototype: Solid
|
||||
get() = when (this) {
|
||||
is SolidReference -> prototype.prototype
|
||||
@ -240,94 +241,3 @@ public fun SolidGroup.newRef(
|
||||
}
|
||||
return children.ref(prototypeName, name?.parseAsName())
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
//
|
||||
///**
|
||||
// * A reference [Solid] to reuse a template object
|
||||
// */
|
||||
//@Serializable
|
||||
//@SerialName("solid.ref")
|
||||
//public class SolidReferenceGroup(
|
||||
// public val refName: Name,
|
||||
//) : VisionGroup(), SolidReference, VisionGroup<Solid>, Solid {
|
||||
//
|
||||
// /**
|
||||
// * Recursively search for defined template in the parent
|
||||
// */
|
||||
// override val prototype: Solid by lazy {
|
||||
// if (parent == null) error("No parent is present for SolidReferenceGroup")
|
||||
// if (parent !is PrototypeHolder) error("Parent does not hold prototypes")
|
||||
// (parent as? PrototypeHolder)?.getPrototype(refName) ?: error("Prototype with name $refName not found")
|
||||
// }
|
||||
//
|
||||
// override val items: Map<NameToken, VisionGroupItem<Solid>>
|
||||
// get() = (prototype as? VisionGroup<*>)?.items
|
||||
// ?.filter { it.key != SolidGroup.PROTOTYPES_TOKEN }
|
||||
// ?.mapValues {
|
||||
// VisionGroupItem.Node(ReferenceChild(this, it.key.asName()))
|
||||
// } ?: emptyMap()
|
||||
//
|
||||
// override val descriptor: MetaDescriptor get() = prototype.descriptor
|
||||
//
|
||||
//
|
||||
// /**
|
||||
// * A ProxyChild is created temporarily only to interact with properties, it does not store any values
|
||||
// * (properties are stored in external cache) and created and destroyed on-demand).
|
||||
// */
|
||||
// private class ReferenceChild(
|
||||
// val owner: SolidReferenceGroup,
|
||||
// private val refName: Name,
|
||||
// ) : SolidReference, VisionGroup<Solid>, Solid {
|
||||
//
|
||||
// override val prototype: Solid by lazy {
|
||||
// if (refName.isEmpty()) {
|
||||
// owner.prototype
|
||||
// } else {
|
||||
// val proto = (owner.prototype).children.get(refName)
|
||||
// ?: error("Prototype with name $refName not found in SolidReferenceGroup ${owner.refName}")
|
||||
// proto as? Solid ?: error("Prototype with name $refName is ${proto::class} but expected Solid")
|
||||
//// proto.unref as? Solid
|
||||
//// ?: error("Prototype with name $refName is ${proto::class} but expected Solid")
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// override val meta: ObservableMutableMeta by lazy {
|
||||
// owner.meta.getOrCreate(childToken(refName).asName())
|
||||
// }
|
||||
//
|
||||
// override val items: Map<NameToken, VisionGroupItem<Solid>>
|
||||
// get() = (prototype as? VisionGroup<*>)?.items
|
||||
// ?.filter { it.key != SolidGroup.PROTOTYPES_TOKEN }
|
||||
// ?.mapValues { (key, _) ->
|
||||
// VisionGroupItem.Node(ReferenceChild(owner, refName + key.asName()))
|
||||
// } ?: emptyMap()
|
||||
//
|
||||
// override var parent: VisionGroup<*>?
|
||||
// get() {
|
||||
// val parentName = refName.cutLast()
|
||||
// return if (parentName.isEmpty()) owner else ReferenceChild(owner, parentName)
|
||||
// }
|
||||
// set(_) {
|
||||
// error("Setting a parent for a reference child is not possible")
|
||||
// }
|
||||
//
|
||||
// override fun invalidateProperty(propertyName: Name) {
|
||||
// owner.invalidateProperty(childPropertyName(refName, propertyName))
|
||||
// }
|
||||
//
|
||||
// override fun update(change: VisionChange) {
|
||||
// change.properties?.let {
|
||||
// updateProperties(it, Name.EMPTY)
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// override val descriptor: MetaDescriptor get() = prototype.descriptor
|
||||
//
|
||||
// }
|
||||
//
|
||||
// public companion object {
|
||||
// public const val REFERENCE_CHILD_PROPERTY_PREFIX: String = "@child"
|
||||
// }
|
||||
//}
|
||||
|
@ -12,13 +12,13 @@ import space.kscience.dataforge.meta.toDynamic
|
||||
import space.kscience.dataforge.names.Name
|
||||
import space.kscience.dataforge.names.asName
|
||||
import space.kscience.visionforge.ElementVisionRenderer
|
||||
import space.kscience.visionforge.JsVisionClient
|
||||
import space.kscience.visionforge.Vision
|
||||
import space.kscience.visionforge.VisionClient
|
||||
import tabulator.Tabulator
|
||||
import tabulator.TabulatorFull
|
||||
|
||||
public class TableVisionJsPlugin : AbstractPlugin(), ElementVisionRenderer {
|
||||
public val visionClient: VisionClient by require(VisionClient)
|
||||
public val visionClient: JsVisionClient by require(JsVisionClient)
|
||||
public val tablesBase: TableVisionPlugin by require(TableVisionPlugin)
|
||||
|
||||
override val tag: PluginTag get() = Companion.tag
|
||||
|
@ -123,8 +123,8 @@ public class ThreeCanvas(
|
||||
element.appendChild(canvas)
|
||||
updateSize()
|
||||
canvas.addEventListener("pointerdown", {
|
||||
val picked = pick()
|
||||
options.onSelect?.invoke(picked?.fullName())
|
||||
val newPicked = pick()
|
||||
options.onSelect?.invoke(newPicked?.fullName())
|
||||
}, false)
|
||||
|
||||
//Attach listener to track mouse changes
|
||||
@ -143,12 +143,12 @@ public class ThreeCanvas(
|
||||
addControls(canvas, options.controls)
|
||||
|
||||
renderer.setAnimationLoop {
|
||||
val picked = pick()
|
||||
val newPicked = pick()
|
||||
|
||||
if (picked != null && this.picked != picked) {
|
||||
this.picked?.toggleHighlight(false, HIGHLIGHT_NAME, HIGHLIGHT_MATERIAL)
|
||||
picked.toggleHighlight(true, HIGHLIGHT_NAME, HIGHLIGHT_MATERIAL)
|
||||
this.picked = picked
|
||||
if (newPicked != null && picked !== newPicked) {
|
||||
picked?.toggleHighlight(false, HIGHLIGHT_NAME, HIGHLIGHT_MATERIAL)
|
||||
newPicked.toggleHighlight(true, HIGHLIGHT_NAME, HIGHLIGHT_MATERIAL)
|
||||
picked = newPicked
|
||||
}
|
||||
|
||||
renderer.render(scene, camera)
|
||||
@ -326,7 +326,7 @@ public class ThreeCanvas(
|
||||
|
||||
public val HIGHLIGHT_MATERIAL: MeshLineMaterial = MeshLineMaterial().apply {
|
||||
color.set(Colors.blue)
|
||||
thickness = 2f
|
||||
thickness = 1f
|
||||
cached = true
|
||||
}
|
||||
//
|
||||
|
@ -7,12 +7,10 @@ import org.w3c.dom.HTMLElement
|
||||
import space.kscience.dataforge.context.*
|
||||
import space.kscience.dataforge.meta.Meta
|
||||
import space.kscience.dataforge.names.*
|
||||
import space.kscience.visionforge.ElementVisionRenderer
|
||||
import space.kscience.visionforge.Vision
|
||||
import space.kscience.visionforge.VisionChildren
|
||||
import space.kscience.visionforge.*
|
||||
import space.kscience.visionforge.solid.*
|
||||
import space.kscience.visionforge.solid.specifications.Canvas3DOptions
|
||||
import space.kscience.visionforge.visible
|
||||
import space.kscience.visionforge.solid.three.set
|
||||
import three.core.Object3D
|
||||
import kotlin.collections.set
|
||||
import kotlin.reflect.KClass
|
||||
@ -23,6 +21,8 @@ public class ThreePlugin : AbstractPlugin(), ElementVisionRenderer {
|
||||
|
||||
public val solids: Solids by require(Solids)
|
||||
|
||||
public val client: VisionClient? get() = context.plugins.get<VisionClient>()
|
||||
|
||||
private val objectFactories = HashMap<KClass<out Solid>, ThreeFactory<*>>()
|
||||
private val compositeFactory = ThreeCompositeFactory(this)
|
||||
|
||||
@ -90,6 +90,8 @@ public class ThreePlugin : AbstractPlugin(), ElementVisionRenderer {
|
||||
|
||||
val child = vision.children.getChild(childName)
|
||||
|
||||
logger.debug { "Changing vision $childName to $child" }
|
||||
|
||||
//removing old object
|
||||
findChild(childName)?.let { oldChild ->
|
||||
oldChild.parent?.remove(oldChild)
|
||||
|
Loading…
Reference in New Issue
Block a user