Strict mode for Three canvas. Styles builders
This commit is contained in:
parent
216be4a6a1
commit
3c0df98f50
@ -1,6 +1,9 @@
|
||||
package ru.mipt.npm.sat
|
||||
|
||||
import hep.dataforge.meta.set
|
||||
import hep.dataforge.vision.solid.*
|
||||
import hep.dataforge.vision.style
|
||||
import hep.dataforge.vision.useStyle
|
||||
import kotlin.math.PI
|
||||
|
||||
internal fun visionOfSatellite(
|
||||
@ -12,7 +15,18 @@ internal fun visionOfSatellite(
|
||||
ySegmentSize: Number = xSegmentSize,
|
||||
fiberDiameter: Number = 1.0,
|
||||
): SolidGroup = SolidGroup {
|
||||
opacity = 0.3
|
||||
val transparent by style {
|
||||
this[SolidMaterial.MATERIAL_OPACITY_KEY] = 0.3
|
||||
}
|
||||
|
||||
val red by style {
|
||||
this[SolidMaterial.MATERIAL_COLOR_KEY] = "red"
|
||||
}
|
||||
|
||||
val blue by style {
|
||||
this[SolidMaterial.MATERIAL_COLOR_KEY] = "blue"
|
||||
}
|
||||
|
||||
val totalXSize = xSegments * xSegmentSize.toDouble()
|
||||
val totalYSize = ySegments * ySegmentSize.toDouble()
|
||||
for (layer in 1..layers) {
|
||||
@ -20,6 +34,7 @@ internal fun visionOfSatellite(
|
||||
for (i in 1..xSegments) {
|
||||
for (j in 1..ySegments) {
|
||||
box(xSegmentSize, ySegmentSize, layerHeight, name = "segment[$i,$j]") {
|
||||
useStyle(transparent)
|
||||
z = (layer - 0.5) * layerHeight.toDouble()
|
||||
x = (i - 0.5) * xSegmentSize.toDouble()
|
||||
y = (j - 0.5) * ySegmentSize.toDouble()
|
||||
@ -29,23 +44,21 @@ internal fun visionOfSatellite(
|
||||
group("fibers") {
|
||||
for (i in 1..xSegments) {
|
||||
cylinder(fiberDiameter, totalYSize) {
|
||||
useStyle(red)
|
||||
rotationX = PI / 2
|
||||
z = (layer - 1.0) * layerHeight.toDouble() + fiberDiameter.toDouble()
|
||||
x = (i - 0.5) * xSegmentSize.toDouble()
|
||||
y = totalYSize/2
|
||||
|
||||
color("red")
|
||||
y = totalYSize / 2
|
||||
}
|
||||
}
|
||||
|
||||
for (j in 1..ySegments) {
|
||||
cylinder(fiberDiameter, totalXSize) {
|
||||
useStyle(blue)
|
||||
rotationY = PI / 2
|
||||
z = (layer) * layerHeight.toDouble() - fiberDiameter.toDouble()
|
||||
y = (j - 0.5) * xSegmentSize.toDouble()
|
||||
x = totalXSize/2
|
||||
|
||||
color("blue")
|
||||
x = totalXSize / 2
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -42,9 +42,9 @@ fun main() {
|
||||
val target = "layer[$randomLayer].segment[$randomI,$randomJ]".toName()
|
||||
val targetVision = sat[target] as Solid
|
||||
targetVision.color("red")
|
||||
delay(300)
|
||||
delay(1000)
|
||||
targetVision.color.clear()
|
||||
delay(10)
|
||||
delay(500)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -37,8 +37,7 @@ public val ThreeCanvasComponent: FunctionalComponent<ThreeCanvasProps> = functio
|
||||
if (canvas == null) {
|
||||
val element = elementRef.current as? HTMLElement ?: error("Canvas element not found")
|
||||
val three: ThreePlugin = props.context.plugins.fetch(ThreePlugin)
|
||||
val newCanvas: ThreeCanvas =
|
||||
three.createCanvas(element, props.options ?: Canvas3DOptions.empty())
|
||||
val newCanvas: ThreeCanvas = three.createCanvas(element, props.options ?: Canvas3DOptions.empty())
|
||||
props.canvasCallback?.invoke(newCanvas)
|
||||
canvas = newCanvas
|
||||
}
|
||||
|
@ -0,0 +1,33 @@
|
||||
package hep.dataforge.vision
|
||||
|
||||
import hep.dataforge.meta.DFExperimental
|
||||
import hep.dataforge.meta.Meta
|
||||
import hep.dataforge.meta.MetaBuilder
|
||||
import kotlin.properties.ReadOnlyProperty
|
||||
|
||||
/**
|
||||
* A reference to a style defined in a specific container
|
||||
*/
|
||||
public class StyleReference(public val owner: VisionGroup, public val name: String)
|
||||
|
||||
private tailrec fun styleIsDefined(vision: Vision, reference: StyleReference): Boolean = when {
|
||||
reference.owner === vision -> true
|
||||
vision.parent == null -> false
|
||||
else -> styleIsDefined(vision.parent!!, reference)
|
||||
}
|
||||
|
||||
@VisionBuilder
|
||||
public fun Vision.useStyle(reference: StyleReference) {
|
||||
//check that style is defined in a parent
|
||||
//check(styleIsDefined(this, reference)) { "Style reference does not belong to a Vision parent" }
|
||||
useStyle(reference.name)
|
||||
}
|
||||
|
||||
@DFExperimental
|
||||
@VisionBuilder
|
||||
public fun VisionGroup.style(builder: MetaBuilder.() -> Unit): ReadOnlyProperty<Any?, StyleReference> =
|
||||
ReadOnlyProperty { _, property ->
|
||||
val styleName = property.name
|
||||
styleSheet.define(styleName, Meta(builder))
|
||||
StyleReference(this, styleName)
|
||||
}
|
@ -111,3 +111,5 @@ public fun Vision.getStyleItems(name: Name): Sequence<MetaItem<*>> {
|
||||
* Collect all styles for this object in a single laminate
|
||||
*/
|
||||
public val Vision.allStyles: Laminate get() = Laminate(styles.mapNotNull(::getStyle))
|
||||
|
||||
|
||||
|
@ -63,7 +63,7 @@ private fun Vision.isolate(manager: VisionManager): Vision {
|
||||
}
|
||||
|
||||
@Serializable
|
||||
public class VisionChange(
|
||||
public data class VisionChange(
|
||||
public val reset: Boolean = false,
|
||||
public val vision: Vision? = null,
|
||||
@Serializable(MetaSerializer::class) public val properties: Meta? = null,
|
||||
|
@ -0,0 +1,18 @@
|
||||
package hep.dataforge.vision
|
||||
|
||||
import hep.dataforge.meta.MetaItem
|
||||
import hep.dataforge.names.Name
|
||||
|
||||
/**
|
||||
* Property containers are used to create a symmetric behaviors for vision properties and style builders
|
||||
*/
|
||||
public interface VisionPropertyContainer<out T> {
|
||||
public fun getProperty(
|
||||
name: Name,
|
||||
inherit: Boolean = false,
|
||||
includeStyles: Boolean = true,
|
||||
includeDefaults: Boolean = true,
|
||||
): MetaItem<*>?
|
||||
|
||||
public fun setProperty(name: Name, item: MetaItem<*>?, notify: Boolean = true)
|
||||
}
|
@ -138,7 +138,7 @@ public class VisionClient : AbstractPlugin() {
|
||||
renderVision(element, change.vision, outputMeta)
|
||||
}
|
||||
|
||||
logger.debug { "Got update $change for output with name $name" }
|
||||
logger.info { "Got update ${change.toString()} for output with name $name" }
|
||||
visionMap[element]?.update(change)
|
||||
?: console.info("Target vision for element $element with name $name not found")
|
||||
} else {
|
||||
|
@ -88,6 +88,7 @@ public fun VisionContainerBuilder<Vision>.group(
|
||||
/**
|
||||
* Define a group with given [name], attach it to this parent and return it.
|
||||
*/
|
||||
@VisionBuilder
|
||||
public fun VisionContainerBuilder<Vision>.group(name: String, action: SolidGroup.() -> Unit = {}): SolidGroup =
|
||||
SolidGroup().apply(action).also { set(name, it) }
|
||||
|
||||
|
@ -130,7 +130,8 @@ public class ThreeCanvas(
|
||||
}
|
||||
}
|
||||
|
||||
public fun attach(element: Element) {
|
||||
internal fun attach(element: Element) {
|
||||
check(element.children.length == 0){"The element for Three canvas is not empty"}
|
||||
element.appendChild(canvas)
|
||||
updateSize()
|
||||
}
|
||||
@ -189,8 +190,10 @@ public class ThreeCanvas(
|
||||
}
|
||||
|
||||
public override fun render(vision: Solid) {
|
||||
//clear old root
|
||||
clear()
|
||||
scene.children.find { it.name == "@root" }?.let {
|
||||
//Throw error is something is already rendered here
|
||||
error("Root object already is present in the canvas")
|
||||
}
|
||||
|
||||
val object3D = three.buildObject3D(vision)
|
||||
object3D.name = "@root"
|
||||
|
@ -136,9 +136,19 @@ public class ThreePlugin : AbstractPlugin(), ElementVisionRenderer {
|
||||
return if (vision is Solid) ElementVisionRenderer.DEFAULT_RATING else ElementVisionRenderer.ZERO_RATING
|
||||
}
|
||||
|
||||
public fun renderSolid(
|
||||
element: Element,
|
||||
vision: Solid,
|
||||
options: Canvas3DOptions,
|
||||
): ThreeCanvas = createCanvas(element, options).apply {
|
||||
render(vision)
|
||||
}
|
||||
|
||||
override fun render(element: Element, vision: Vision, meta: Meta) {
|
||||
createCanvas(element, Canvas3DOptions.read(meta)).render(
|
||||
vision as? Solid ?: error("Solid expected but ${vision::class} is found")
|
||||
renderSolid(
|
||||
element,
|
||||
vision as? Solid ?: error("Solid expected but ${vision::class} is found"),
|
||||
Canvas3DOptions.read(meta)
|
||||
)
|
||||
}
|
||||
|
||||
@ -153,7 +163,7 @@ public fun ThreePlugin.render(
|
||||
element: HTMLElement,
|
||||
obj: Solid,
|
||||
options: Canvas3DOptions.() -> Unit = {},
|
||||
): ThreeCanvas = createCanvas(element, Canvas3DOptions(options)).apply { render(obj) }
|
||||
): ThreeCanvas = renderSolid(element, obj, Canvas3DOptions(options))
|
||||
|
||||
internal operator fun Object3D.set(token: NameToken, object3D: Object3D) {
|
||||
object3D.name = token.toString()
|
||||
|
Loading…
Reference in New Issue
Block a user