Fix material display and useProperties
This commit is contained in:
@@ -33,6 +33,6 @@ class GDMLVisionTest {
|
||||
val child = cubes[Name.of("composite-000","segment-0")]
|
||||
assertNotNull(child)
|
||||
child.properties.setValue(SolidMaterial.MATERIAL_COLOR_KEY, "red".asValue())
|
||||
assertEquals("red", child.properties[SolidMaterial.MATERIAL_COLOR_KEY].string)
|
||||
assertEquals("red", child.readProperty(SolidMaterial.MATERIAL_COLOR_KEY).string)
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,7 @@ import kotlinx.coroutines.channels.BufferOverflow
|
||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||
import kotlinx.coroutines.flow.SharedFlow
|
||||
import kotlinx.coroutines.flow.onCompletion
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.serialization.EncodeDefault
|
||||
import kotlinx.serialization.ExperimentalSerializationApi
|
||||
import kotlinx.serialization.Serializable
|
||||
@@ -22,20 +23,19 @@ public abstract class AbstractVision(
|
||||
|
||||
@Transient
|
||||
private val _eventFlow =
|
||||
MutableSharedFlow<VisionEvent>(extraBufferCapacity = 1, onBufferOverflow = BufferOverflow.DROP_OLDEST)
|
||||
MutableSharedFlow<VisionEvent>(extraBufferCapacity = 100, onBufferOverflow = BufferOverflow.DROP_OLDEST)
|
||||
|
||||
override val eventFlow: SharedFlow<VisionEvent> get() = _eventFlow
|
||||
|
||||
protected fun emitEvent(event: VisionEvent) {
|
||||
_eventFlow.tryEmit(event)
|
||||
// val context = manager?.context
|
||||
// if (context == null) {
|
||||
// _eventFlow.tryEmit(event)
|
||||
// } else {
|
||||
// context.launch {
|
||||
// _eventFlow.emit(event)
|
||||
// }
|
||||
// }
|
||||
val context = manager?.context
|
||||
if (context == null) {
|
||||
_eventFlow.tryEmit(event)
|
||||
} else {
|
||||
context.launch {
|
||||
_eventFlow.emit(event)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
init {
|
||||
|
||||
@@ -92,10 +92,10 @@ public interface Vision : Described, Provider {
|
||||
}
|
||||
}
|
||||
|
||||
internal fun Vision.isInheritedProperty(name: Name): Boolean = descriptor?.get(name)?.inherited ?: false
|
||||
internal fun Vision.isInheritedProperty(name: String): Boolean = descriptor?.get(name)?.inherited ?: false
|
||||
internal fun Vision.isStyledProperty(name: Name): Boolean = descriptor?.get(name)?.usesStyles ?: true
|
||||
internal fun Vision.isStyledProperty(name: String): Boolean = descriptor?.get(name)?.usesStyles ?: true
|
||||
internal fun Vision.isInheritedProperty(name: Name): Boolean = descriptor?.get(name)?.inherited == true
|
||||
internal fun Vision.isInheritedProperty(name: String): Boolean = descriptor?.get(name)?.inherited == true
|
||||
internal fun Vision.isStyledProperty(name: Name): Boolean = descriptor?.get(name)?.usesStyles != false
|
||||
internal fun Vision.isStyledProperty(name: String): Boolean = descriptor?.get(name)?.usesStyles != false
|
||||
|
||||
public fun Vision.readProperty(
|
||||
name: String,
|
||||
@@ -126,7 +126,7 @@ public interface MutableVision : Vision {
|
||||
} else super.receiveEvent(event)
|
||||
}
|
||||
|
||||
public fun writeProperty(
|
||||
public fun mutableProperty(
|
||||
name: Name,
|
||||
inherited: Boolean = isInheritedProperty(name),
|
||||
useStyles: Boolean = isStyledProperty(name),
|
||||
@@ -137,7 +137,9 @@ public interface MutableVision : Vision {
|
||||
val defaultMeta = descriptor?.defaultNode?.get(name)
|
||||
val listOfMeta = listOf(styleMeta, inheritMeta, defaultMeta)
|
||||
|
||||
return properties.getOrCreate(name).withDefault(Laminate(listOfMeta))
|
||||
return properties.getOrCreate(name).withDefault{
|
||||
listOfMeta.firstNotNullOfOrNull { it[name] }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -148,7 +150,7 @@ public fun MutableVision.properties(block: MutableMeta.() -> Unit) {
|
||||
public fun MutableVision.writeProperties(
|
||||
inherited: Boolean = false,
|
||||
useStyles: Boolean = true,
|
||||
): MutableMeta = writeProperty(Name.EMPTY, inherited, useStyles)
|
||||
): MutableMeta = mutableProperty(Name.EMPTY, inherited, useStyles)
|
||||
|
||||
/**
|
||||
* Control visibility of the element
|
||||
@@ -177,14 +179,14 @@ public var MutableVision.styles: List<String>
|
||||
}
|
||||
|
||||
public fun MutableVision.setStyle(styleName: String, style: Meta) {
|
||||
properties[Vision.STYLESHEET_KEY + styleName] = style
|
||||
properties[STYLESHEET_KEY + styleName] = style
|
||||
}
|
||||
|
||||
/**
|
||||
* Define or modify a style with given [styleName]. The style is not used immediately. Call [useStyle] to enable it for this vision
|
||||
*/
|
||||
public fun MutableVision.updateStyle(styleName: String, block: MutableMeta.() -> Unit) {
|
||||
properties.getOrCreate(Vision.STYLESHEET_KEY + styleName).block()
|
||||
properties.getOrCreate(STYLESHEET_KEY + styleName).block()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -201,7 +203,8 @@ public fun MutableVision.useStyle(styleName: String) {
|
||||
* Resolve a style with given name for given [Vision]. The style is not necessarily applied to this [Vision].
|
||||
*/
|
||||
public fun Vision.getStyle(name: String): Meta? =
|
||||
properties[STYLESHEET_KEY + name] ?: parent?.getStyle(name)
|
||||
readProperty(STYLESHEET_KEY + name, inherited = true, useStyles = false)
|
||||
//properties[STYLESHEET_KEY + name] ?: parent?.getStyle(name)
|
||||
|
||||
/**
|
||||
* Resolve a property from all styles
|
||||
|
||||
@@ -11,8 +11,18 @@ import space.kscience.dataforge.names.Name
|
||||
import space.kscience.dataforge.names.parseAsName
|
||||
import kotlin.reflect.KProperty1
|
||||
|
||||
private fun Vision.withAncestors(): List<Vision> = buildList {
|
||||
add(this@withAncestors)
|
||||
var parent = parent
|
||||
while (parent != null) {
|
||||
add(parent)
|
||||
parent = parent.parent
|
||||
}
|
||||
}
|
||||
|
||||
public fun Vision.inheritedEventFlow(): Flow<VisionEvent> =
|
||||
parent?.let { parent -> merge(eventFlow, parent.inheritedEventFlow()) } ?: eventFlow
|
||||
parent?.let { withAncestors().map { it.eventFlow }.merge() } ?: eventFlow
|
||||
|
||||
|
||||
/**
|
||||
* Create a flow of a specific property
|
||||
@@ -69,31 +79,28 @@ public fun Vision.useProperty(
|
||||
inherited: Boolean = isInheritedProperty(propertyName),
|
||||
useStyles: Boolean = isStyledProperty(propertyName),
|
||||
scope: CoroutineScope = manager?.context ?: error("Orphan Vision can't observe properties. Use explicit scope."),
|
||||
callback: suspend (Meta) -> Unit,
|
||||
callback: suspend (Meta?) -> Unit,
|
||||
): Job = scope.launch {
|
||||
//Pass initial value synchronously
|
||||
callback(readProperty(propertyName, inherited, useStyles))
|
||||
|
||||
readProperty(propertyName, inherited, useStyles)?.let { callback(it) }
|
||||
|
||||
val combinedFlow = if (inherited) {
|
||||
if (inherited) {
|
||||
inheritedEventFlow()
|
||||
} else {
|
||||
eventFlow
|
||||
}
|
||||
|
||||
combinedFlow.filterIsInstance<VisionPropertyChangedEvent>().onEach { event ->
|
||||
}.filterIsInstance<VisionPropertyChangedEvent>().onEach { event ->
|
||||
if (event.propertyName == propertyName || (useStyles && event.propertyName == Vision.STYLE_KEY)) {
|
||||
readProperty(event.propertyName, inherited, useStyles)?.let { callback(it) }
|
||||
callback(readProperty(event.propertyName, inherited, useStyles))
|
||||
}
|
||||
}.collect()
|
||||
}
|
||||
|
||||
public fun Vision.useProperty(
|
||||
propertyName: String,
|
||||
inherited: Boolean = descriptor?.get(propertyName)?.inherited ?: false,
|
||||
useStyles: Boolean = descriptor?.get(propertyName)?.usesStyles ?: true,
|
||||
inherited: Boolean = descriptor?.get(propertyName)?.inherited == true,
|
||||
useStyles: Boolean = descriptor?.get(propertyName)?.usesStyles != false,
|
||||
scope: CoroutineScope = manager?.context ?: error("Orphan Vision can't observe properties. Use explicit scope."),
|
||||
callback: suspend (Meta) -> Unit,
|
||||
callback: suspend (Meta?) -> Unit,
|
||||
): Job = useProperty(propertyName.parseAsName(), inherited, useStyles, scope, callback)
|
||||
|
||||
public fun <V : Vision, T> V.useProperty(
|
||||
@@ -109,9 +116,14 @@ public fun <V : Vision, T> V.useProperty(
|
||||
*/
|
||||
public fun Vision.onPropertyChange(
|
||||
scope: CoroutineScope = manager?.context ?: error("Orphan Vision can't observe properties. Use explicit scope."),
|
||||
callback: suspend (Name) -> Unit,
|
||||
): Job = inheritedEventFlow().filterIsInstance<VisionPropertyChangedEvent>().onEach {
|
||||
callback(it.propertyName)
|
||||
inherited: Boolean = true,
|
||||
callback: suspend (name: Name, value: Meta?) -> Unit,
|
||||
): Job = if (inherited) {
|
||||
inheritedEventFlow()
|
||||
} else {
|
||||
eventFlow
|
||||
}.filterIsInstance<VisionPropertyChangedEvent>().onEach {
|
||||
callback(it.propertyName, it.propertyValue)
|
||||
}.launchIn(scope)
|
||||
|
||||
/**
|
||||
|
||||
@@ -42,7 +42,7 @@ internal class VisionPropertyTest {
|
||||
@Test
|
||||
fun testPropertyEdit() {
|
||||
val vision = SimpleVisionGroup()
|
||||
vision.writeProperty("fff.ddd".parseAsName()).apply {
|
||||
vision.mutableProperty("fff.ddd".parseAsName()).apply {
|
||||
value = 2.asValue()
|
||||
}
|
||||
assertEquals(2, vision.readProperty("fff.ddd")?.int)
|
||||
@@ -52,7 +52,7 @@ internal class VisionPropertyTest {
|
||||
@Test
|
||||
fun testPropertyUpdate() {
|
||||
val vision = SimpleVisionGroup()
|
||||
vision.writeProperty("fff".asName()).updateWith(TestScheme) {
|
||||
vision.mutableProperty("fff".asName()).updateWith(TestScheme) {
|
||||
ddd = 2
|
||||
}
|
||||
assertEquals(2, vision.readProperty("fff.ddd")?.int)
|
||||
|
||||
@@ -3,13 +3,14 @@ package space.kscience.visionforge.solid
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
import space.kscience.dataforge.meta.MutableMeta
|
||||
import space.kscience.dataforge.names.Name
|
||||
import space.kscience.dataforge.meta.update
|
||||
import space.kscience.kmath.geometry.component1
|
||||
import space.kscience.kmath.geometry.component2
|
||||
import space.kscience.kmath.geometry.euclidean2d.Float32Vector2D
|
||||
import space.kscience.kmath.geometry.euclidean3d.Float32Vector3D
|
||||
import space.kscience.visionforge.MutableVisionContainer
|
||||
import space.kscience.visionforge.VisionBuilder
|
||||
import space.kscience.visionforge.properties
|
||||
|
||||
|
||||
/**
|
||||
@@ -93,7 +94,9 @@ public class Extruded(
|
||||
}
|
||||
|
||||
internal fun build(): Extruded = Extruded(shape, layers).apply {
|
||||
this.properties[Name.EMPTY] = this@Builder.properties
|
||||
properties {
|
||||
update(this@Builder.properties)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,7 +4,6 @@ import space.kscience.dataforge.meta.*
|
||||
import space.kscience.dataforge.meta.descriptors.MetaDescriptor
|
||||
import space.kscience.dataforge.meta.descriptors.ValueRestriction
|
||||
import space.kscience.dataforge.meta.descriptors.value
|
||||
import space.kscience.dataforge.meta.set
|
||||
import space.kscience.dataforge.names.Name
|
||||
import space.kscience.dataforge.names.asName
|
||||
import space.kscience.dataforge.names.plus
|
||||
@@ -114,12 +113,12 @@ public val Solid.color: ColorAccessor
|
||||
get() = ColorAccessor(writeProperties(inherited = true), MATERIAL_COLOR_KEY)
|
||||
|
||||
public var Solid.material: SolidMaterial?
|
||||
get() = properties[MATERIAL_KEY]?.let { SolidMaterial.read(it)}
|
||||
get() = readProperty(MATERIAL_KEY)?.let { SolidMaterial.read(it)}
|
||||
set(value) = properties.set(MATERIAL_KEY, value?.meta)
|
||||
|
||||
@VisionBuilder
|
||||
public fun Solid.material(builder: SolidMaterial.() -> Unit) {
|
||||
writeProperty(MATERIAL_KEY, inherited = false, useStyles = false).updateWith(SolidMaterial, builder)
|
||||
mutableProperty(MATERIAL_KEY, inherited = false, useStyles = false).updateWith(SolidMaterial, builder)
|
||||
}
|
||||
|
||||
public var Solid.opacity: Number?
|
||||
@@ -132,5 +131,5 @@ public var Solid.opacity: Number?
|
||||
@VisionBuilder
|
||||
public fun Solid.edges(enabled: Boolean = true, block: SolidMaterial.() -> Unit = {}) {
|
||||
properties[SolidMaterial.EDGES_ENABLED_KEY] = enabled
|
||||
SolidMaterial.write(writeProperty(SolidMaterial.EDGES_MATERIAL_KEY)).apply(block)
|
||||
SolidMaterial.write(mutableProperty(SolidMaterial.EDGES_MATERIAL_KEY)).apply(block)
|
||||
}
|
||||
@@ -109,7 +109,7 @@ public class SolidReference(
|
||||
return if (listOfMeta.all { it == null }) null else Laminate(listOfMeta)
|
||||
}
|
||||
|
||||
override fun writeProperty(
|
||||
override fun mutableProperty(
|
||||
name: Name,
|
||||
inherited: Boolean,
|
||||
useStyles: Boolean
|
||||
@@ -172,7 +172,7 @@ private class SolidReferenceChild(
|
||||
|
||||
override val properties: MutableMeta = owner.properties.view(childToken.asName())
|
||||
|
||||
override fun writeProperty(
|
||||
override fun mutableProperty(
|
||||
name: Name,
|
||||
inherited: Boolean,
|
||||
useStyles: Boolean
|
||||
|
||||
@@ -3,13 +3,14 @@ package space.kscience.visionforge.solid
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
import space.kscience.dataforge.meta.MutableMeta
|
||||
import space.kscience.dataforge.names.Name
|
||||
import space.kscience.dataforge.meta.update
|
||||
import space.kscience.kmath.geometry.component1
|
||||
import space.kscience.kmath.geometry.component2
|
||||
import space.kscience.kmath.geometry.euclidean3d.Float32Vector3D
|
||||
import space.kscience.kmath.structures.Float32
|
||||
import space.kscience.visionforge.MutableVisionContainer
|
||||
import space.kscience.visionforge.VisionBuilder
|
||||
import space.kscience.visionforge.properties
|
||||
|
||||
|
||||
private inline fun <T> Iterable<T>.sumOf(selector: (T) -> Float32): Float32 {
|
||||
@@ -155,7 +156,9 @@ public class Surface(
|
||||
}
|
||||
|
||||
internal fun build(): Surface = Surface(layers).apply {
|
||||
properties[Name.EMPTY] = this@Builder.properties
|
||||
properties {
|
||||
update(this@Builder.properties)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
package space.kscience.visionforge.solid.transform
|
||||
|
||||
import space.kscience.dataforge.meta.update
|
||||
import space.kscience.dataforge.misc.DFExperimental
|
||||
import space.kscience.dataforge.names.Name
|
||||
import space.kscience.kmath.complex.QuaternionAlgebra
|
||||
|
||||
import space.kscience.visionforge.properties
|
||||
import space.kscience.visionforge.solid.*
|
||||
|
||||
private operator fun Number.plus(other: Number) = toFloat() + other.toFloat()
|
||||
@@ -18,7 +18,9 @@ internal fun Solid.updateFrom(other: Solid): Solid {
|
||||
scaleX *= other.scaleX
|
||||
scaleY *= other.scaleY
|
||||
scaleZ *= other.scaleZ
|
||||
properties[Name.EMPTY] = other.properties
|
||||
properties {
|
||||
update(other.properties)
|
||||
}
|
||||
return this
|
||||
}
|
||||
|
||||
|
||||
@@ -7,6 +7,8 @@ import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
internal val testSolids = Global.request(Solids)
|
||||
internal val testVisionManager = testSolids.visionManager
|
||||
|
||||
|
||||
class SolidPluginTest {
|
||||
val vision = testSolids.solidGroup {
|
||||
@@ -20,14 +22,13 @@ class SolidPluginTest {
|
||||
@DFExperimental
|
||||
@Test
|
||||
fun testPluginConverter() {
|
||||
val visionManager = Global.request(Solids).visionManager
|
||||
val meta = visionManager.encodeToMeta(vision)
|
||||
val meta = testVisionManager.encodeToMeta(vision)
|
||||
|
||||
val reconstructed = visionManager.decodeFromMeta(meta) as SolidGroup
|
||||
val reconstructed = testVisionManager.decodeFromMeta(meta) as SolidGroup
|
||||
|
||||
assertEquals(
|
||||
visionManager.encodeToJsonElement(vision["aBox"]!!),
|
||||
visionManager.encodeToJsonElement(reconstructed["aBox"]!!)
|
||||
testVisionManager.encodeToJsonElement(vision["aBox"]!!),
|
||||
testVisionManager.encodeToJsonElement(reconstructed["aBox"]!!)
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -72,6 +72,7 @@ class SolidPropertyTest {
|
||||
val group = SolidGroup().apply {
|
||||
updateStyle("testStyle") {
|
||||
SolidMaterial.MATERIAL_COLOR_KEY put "#555555"
|
||||
SolidMaterial.MATERIAL_OPACITY_KEY put 0.3
|
||||
}
|
||||
solidGroup {
|
||||
box = box(100, 100, 100) {
|
||||
@@ -80,6 +81,7 @@ class SolidPropertyTest {
|
||||
}
|
||||
}
|
||||
assertEquals("#555555", box?.color?.string)
|
||||
assertEquals(0.3, box?.opacity)
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -88,6 +90,7 @@ class SolidPropertyTest {
|
||||
val group = testSolids.solidGroup {
|
||||
updateStyle("testStyle") {
|
||||
SolidMaterial.MATERIAL_COLOR_KEY put "#555555"
|
||||
SolidMaterial.MATERIAL_OPACITY_KEY put 0.3
|
||||
}
|
||||
prototypes {
|
||||
box(100, 100, 100, name = "box") {
|
||||
@@ -99,5 +102,6 @@ class SolidPropertyTest {
|
||||
}
|
||||
}
|
||||
assertEquals("#555555", box!!.color.string)
|
||||
assertEquals(0.3, box.opacity)
|
||||
}
|
||||
}
|
||||
@@ -31,6 +31,6 @@ class SolidReferenceTest {
|
||||
val serialized = Solids.jsonForSolids.encodeToJsonElement(groupWithReference)
|
||||
val deserialized = Solids.jsonForSolids.decodeFromJsonElement(SolidGroup.serializer(), serialized)
|
||||
assertEquals(groupWithReference.visions["test"]?.color?.string, deserialized.visions["test"]?.color?.string)
|
||||
assertEquals("blue", (deserialized.get("test") as Solid).color.string)
|
||||
assertEquals("blue", (deserialized["test"] as Solid).color.string)
|
||||
}
|
||||
}
|
||||
@@ -1,26 +1,32 @@
|
||||
package space.kscience.visionforge.solid
|
||||
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.channels.Channel
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.flow.consumeAsFlow
|
||||
import kotlinx.coroutines.flow.take
|
||||
import kotlinx.coroutines.flow.toList
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import space.kscience.dataforge.context.Global
|
||||
import space.kscience.dataforge.context.request
|
||||
import kotlinx.coroutines.withContext
|
||||
import space.kscience.dataforge.meta.Meta
|
||||
import space.kscience.dataforge.meta.string
|
||||
import space.kscience.dataforge.names.asName
|
||||
import space.kscience.visionforge.VisionChange
|
||||
import space.kscience.visionforge.getOrCreateChange
|
||||
import space.kscience.visionforge.useProperty
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertTrue
|
||||
import kotlin.time.Duration.Companion.seconds
|
||||
|
||||
internal class VisionUpdateTest {
|
||||
val solidManager = Global.request(Solids)
|
||||
val visionManager = solidManager.visionManager
|
||||
|
||||
@Test
|
||||
fun testVisionUpdate() = runTest {
|
||||
val targetVision = testSolids.solidGroup {
|
||||
box(200, 200, 200, name = "origin")
|
||||
}
|
||||
val dif = visionManager.VisionChange {
|
||||
val dif = testVisionManager.VisionChange {
|
||||
solidGroup("top") {
|
||||
color(123)
|
||||
box(100, 100, 100)
|
||||
@@ -46,7 +52,7 @@ internal class VisionUpdateTest {
|
||||
|
||||
@Test
|
||||
fun testVisionChangeSerialization() {
|
||||
val change = visionManager.VisionChange {
|
||||
val change = testVisionManager.VisionChange {
|
||||
solidGroup("top") {
|
||||
color(123)
|
||||
box(100, 100, 100)
|
||||
@@ -60,9 +66,41 @@ internal class VisionUpdateTest {
|
||||
Meta("red")
|
||||
)
|
||||
}
|
||||
val serialized = visionManager.jsonFormat.encodeToString(VisionChange.serializer(), change)
|
||||
val serialized = testVisionManager.jsonFormat.encodeToString(VisionChange.serializer(), change)
|
||||
println(serialized)
|
||||
val reconstructed = visionManager.jsonFormat.decodeFromString(VisionChange.serializer(), serialized)
|
||||
val reconstructed = testVisionManager.jsonFormat.decodeFromString(VisionChange.serializer(), serialized)
|
||||
assertEquals(change.properties, reconstructed.properties)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun useProperty() = runTest(timeout = 1.seconds) {
|
||||
withContext(Dispatchers.Default) {
|
||||
val group = testSolids.solidGroup {
|
||||
box(100, 100, 100)
|
||||
}
|
||||
|
||||
val box = group.visions.values.first()
|
||||
|
||||
val collected = Channel<String?>(5)
|
||||
|
||||
box.useProperty(SolidMaterial.MATERIAL_COLOR_KEY) {
|
||||
println(it.string)
|
||||
collected.send(it.string)
|
||||
}
|
||||
|
||||
delay(1)
|
||||
|
||||
group.color("red")
|
||||
group.color("green")
|
||||
box.color("blue")
|
||||
|
||||
assertEquals("blue", box.readProperty(SolidMaterial.MATERIAL_COLOR_KEY).string)
|
||||
assertEquals("blue", box.color.string)
|
||||
|
||||
val list = collected.consumeAsFlow().take(4).toList()
|
||||
|
||||
assertEquals(null, list.first())
|
||||
assertEquals("blue", list.last())
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -21,7 +21,7 @@ public object ThreeAmbientLightFactory : ThreeFactory<AmbientLightSource> {
|
||||
}
|
||||
|
||||
if (observe) {
|
||||
vision.onPropertyChange(three.context) { propertyName: Name ->
|
||||
vision.onPropertyChange(three.context) { propertyName: Name, _ ->
|
||||
when (propertyName) {
|
||||
Vision.VISIBLE_KEY -> res.visible = vision.visible ?: true
|
||||
SolidMaterial.COLOR_KEY -> res.color = vision.color.threeColor() ?: Color(0x404040)
|
||||
|
||||
@@ -12,7 +12,7 @@ public object ThreeAxesFactory : ThreeFactory<AxesSolid> {
|
||||
val res = AxesHelper(vision.size.toInt())
|
||||
|
||||
if (observe) {
|
||||
vision.onPropertyChange(three.context) { propertyName ->
|
||||
vision.onPropertyChange(three.context) { propertyName, _ ->
|
||||
res.updateProperty(vision, propertyName)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,7 +52,7 @@ public class ThreeCompositeFactory(public val three: ThreePlugin) : ThreeFactory
|
||||
applyProperties(vision)
|
||||
|
||||
if (observe) {
|
||||
vision.onPropertyChange(three.context) { name ->
|
||||
vision.onPropertyChange(three.context) { name, _ ->
|
||||
when {
|
||||
//name.startsWith(WIREFRAME_KEY) -> mesh.applyWireFrame(obj)
|
||||
name.startsWith(EDGES_KEY) -> applyEdges(vision)
|
||||
|
||||
@@ -65,7 +65,7 @@ public fun Object3D.updatePosition(vision: Vision) {
|
||||
* Update non-position non-geometry property
|
||||
*/
|
||||
public fun Object3D.updateProperty(source: Solid, propertyName: Name) {
|
||||
// console.log("$source updated $propertyName with ${source.computeProperty(propertyName)}")
|
||||
//console.log("${source::class} updated $propertyName with ${source.readProperty(propertyName, inherited = true)}")
|
||||
if (isMesh(this) && propertyName.startsWith(MATERIAL_KEY)) {
|
||||
updateMaterialProperty(source, propertyName)
|
||||
} else if (
|
||||
@@ -76,7 +76,7 @@ public fun Object3D.updateProperty(source: Solid, propertyName: Name) {
|
||||
//update position of mesh using this object
|
||||
updatePosition(source)
|
||||
} else if (propertyName == Vision.VISIBLE_KEY) {
|
||||
visible = source.visible ?: true
|
||||
visible = source.visible != false
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ public object ThreeLabelFactory : ThreeFactory<SolidLabel> {
|
||||
setMaterial(vision)
|
||||
updatePosition(vision)
|
||||
if (observe) {
|
||||
vision.onPropertyChange(three.context) {
|
||||
vision.onPropertyChange(three.context) { _, _ ->
|
||||
//TODO
|
||||
three.logger.warn { "Label parameter change not implemented" }
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ public object ThreeLineFactory : ThreeFactory<PolyLine> {
|
||||
}
|
||||
|
||||
val material = ThreeMaterials.getLineMaterial(
|
||||
vision.properties[SolidMaterial.MATERIAL_KEY],
|
||||
vision.readProperty(SolidMaterial.MATERIAL_KEY),
|
||||
false
|
||||
)
|
||||
|
||||
@@ -36,7 +36,7 @@ public object ThreeLineFactory : ThreeFactory<PolyLine> {
|
||||
//layers.enable(obj.layer)
|
||||
//add listener to object properties
|
||||
if(observe) {
|
||||
vision.onPropertyChange(three.context) { propertyName ->
|
||||
vision.onPropertyChange(three.context) { propertyName,_ ->
|
||||
updateProperty(vision, propertyName)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,6 @@ import space.kscience.dataforge.names.asName
|
||||
import space.kscience.dataforge.names.plus
|
||||
import space.kscience.visionforge.Colors
|
||||
import space.kscience.visionforge.Vision
|
||||
import space.kscience.visionforge.getStyleNodes
|
||||
import space.kscience.visionforge.solid.ColorAccessor
|
||||
import space.kscience.visionforge.solid.SolidMaterial
|
||||
import space.kscience.visionforge.solid.SolidReference
|
||||
@@ -92,7 +91,7 @@ public object ThreeMaterials {
|
||||
private val visionMaterialCache = HashMap<Vision, Material>()
|
||||
|
||||
internal fun cacheMaterial(vision: Vision): Material = visionMaterialCache.getOrPut(vision) {
|
||||
buildMaterial(vision.properties[SolidMaterial.MATERIAL_KEY] ?: Meta.EMPTY).apply {
|
||||
buildMaterial(vision.readProperty(SolidMaterial.MATERIAL_KEY) ?: Meta.EMPTY).apply {
|
||||
cached = true
|
||||
}
|
||||
}
|
||||
@@ -133,8 +132,8 @@ internal var Material.cached: Boolean
|
||||
|
||||
public fun Mesh.setMaterial(vision: Vision) {
|
||||
if (
|
||||
vision.properties[SolidMaterial.MATERIAL_KEY] == null
|
||||
&& vision.getStyleNodes(SolidMaterial.MATERIAL_KEY).isEmpty()
|
||||
vision.readProperty(SolidMaterial.MATERIAL_KEY) == null
|
||||
// && vision.getStyleNodes(SolidMaterial.MATERIAL_KEY).isEmpty()
|
||||
) {
|
||||
//if this is a reference, use material of the prototype
|
||||
if (vision is SolidReference) {
|
||||
@@ -146,7 +145,7 @@ public fun Mesh.setMaterial(vision: Vision) {
|
||||
} ?: ThreeMaterials.cacheMaterial(vision)
|
||||
}
|
||||
} else {
|
||||
material = ThreeMaterials.buildMaterial(vision.properties[SolidMaterial.MATERIAL_KEY] ?: Meta.EMPTY)
|
||||
material = ThreeMaterials.buildMaterial(vision.readProperty(SolidMaterial.MATERIAL_KEY) ?: Meta.EMPTY)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -162,20 +161,20 @@ public fun Mesh.updateMaterialProperty(vision: Vision, propertyName: Name) {
|
||||
when (propertyName) {
|
||||
SolidMaterial.MATERIAL_COLOR_KEY -> {
|
||||
material.asDynamic().color =
|
||||
vision.properties[SolidMaterial.MATERIAL_COLOR_KEY]
|
||||
vision.readProperty(SolidMaterial.MATERIAL_COLOR_KEY)
|
||||
?.threeColor()
|
||||
?: ThreeMaterials.DEFAULT_COLOR
|
||||
}
|
||||
|
||||
SolidMaterial.SPECULAR_COLOR_KEY -> {
|
||||
material.asDynamic().specular =
|
||||
vision.properties[SolidMaterial.SPECULAR_COLOR_KEY]
|
||||
vision.readProperty(SolidMaterial.SPECULAR_COLOR_KEY)
|
||||
?.threeColor()
|
||||
?: ThreeMaterials.DEFAULT_COLOR
|
||||
}
|
||||
|
||||
SolidMaterial.MATERIAL_EMISSIVE_COLOR_KEY -> {
|
||||
material.asDynamic().emissive = vision.properties[SolidMaterial.MATERIAL_EMISSIVE_COLOR_KEY]
|
||||
material.asDynamic().emissive = vision.readProperty(SolidMaterial.MATERIAL_EMISSIVE_COLOR_KEY)
|
||||
?.threeColor()
|
||||
?: ThreeMaterials.BLACK_COLOR
|
||||
}
|
||||
|
||||
@@ -39,7 +39,8 @@ public abstract class ThreeMeshFactory<in T : Solid>(
|
||||
|
||||
if (observe) {
|
||||
//add listener to object properties
|
||||
vision.onPropertyChange(three.context) { name ->
|
||||
vision.onPropertyChange(three.context) { name, _ ->
|
||||
console.log("$mesh updated $name with ${vision.readProperty(name, inherited = true)}")
|
||||
when {
|
||||
name.startsWith(Solid.GEOMETRY_KEY) -> {
|
||||
val oldGeometry = mesh.geometry
|
||||
@@ -76,7 +77,7 @@ public fun Mesh.applyEdges(vision: Solid) {
|
||||
val edges = children.find { it.name == EDGES_OBJECT_NAME } as? LineSegments
|
||||
//inherited edges definition, enabled by default
|
||||
if (vision.readProperty(EDGES_ENABLED_KEY, inherited = false)?.boolean != false) {
|
||||
val material = ThreeMaterials.getLineMaterial(vision.properties[EDGES_MATERIAL_KEY], true)
|
||||
val material = ThreeMaterials.getLineMaterial(vision.readProperty(EDGES_MATERIAL_KEY), true)
|
||||
if (edges == null) {
|
||||
add(
|
||||
LineSegments(
|
||||
|
||||
@@ -32,7 +32,7 @@ public object ThreeMeshLineFactory : ThreeFactory<PolyLine> {
|
||||
//layers.enable(obj.layer)
|
||||
//add listener to object properties
|
||||
if (observe) {
|
||||
vision.onPropertyChange(three.context) { propertyName ->
|
||||
vision.onPropertyChange(three.context) { propertyName, _ ->
|
||||
updateProperty(vision, propertyName)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,7 +71,7 @@ public class ThreePlugin : AbstractPlugin(), ComposeHtmlVisionRenderer {
|
||||
try {
|
||||
val object3D = buildObject3D(
|
||||
child,
|
||||
if (name.body == SolidGroup.STATIC_TOKEN_BODY) false else observe
|
||||
// if (name.body == SolidGroup.STATIC_TOKEN_BODY) false else observe
|
||||
)
|
||||
// disable tracking changes for statics
|
||||
group[name] = object3D
|
||||
@@ -89,6 +89,7 @@ public class ThreePlugin : AbstractPlugin(), ComposeHtmlVisionRenderer {
|
||||
when (event) {
|
||||
is VisionPropertyChangedEvent -> {
|
||||
val propertyName = event.propertyName
|
||||
console.log("$vision updated $propertyName with ${vision.readProperty(propertyName, inherited = true)}")
|
||||
if (
|
||||
propertyName.startsWith(Solid.POSITION_KEY) ||
|
||||
propertyName.startsWith(Solid.ROTATION_KEY) ||
|
||||
@@ -97,13 +98,13 @@ public class ThreePlugin : AbstractPlugin(), ComposeHtmlVisionRenderer {
|
||||
//update position of mesh using this object
|
||||
updatePosition(vision)
|
||||
} else if (propertyName == Vision.VISIBLE_KEY) {
|
||||
visible = vision.visible ?: true
|
||||
visible = vision.visible != false
|
||||
}
|
||||
}
|
||||
is VisionGroupCompositionChangedEvent -> {
|
||||
val childName = event.childName
|
||||
|
||||
val child = vision.get(childName)
|
||||
val child = vision[childName]
|
||||
|
||||
logger.debug { "Changing vision $childName to $child" }
|
||||
|
||||
|
||||
@@ -21,8 +21,8 @@ public object ThreePointLightFactory : ThreeFactory<PointLightSource> {
|
||||
updatePosition(vision)
|
||||
}
|
||||
|
||||
if(observe) {
|
||||
vision.onPropertyChange(three.context) { name ->
|
||||
if (observe) {
|
||||
vision.onPropertyChange(three.context) { name, _ ->
|
||||
when (name) {
|
||||
LightSource::color.name.asName() -> res.color = vision.color.threeColor() ?: DEFAULT_COLOR
|
||||
LightSource::intensity.name.asName() -> res.intensity = vision.intensity.toDouble()
|
||||
|
||||
@@ -49,7 +49,7 @@ public object ThreeReferenceFactory : ThreeFactory<SolidReference> {
|
||||
//TODO apply child properties
|
||||
|
||||
if (observe) {
|
||||
vision.onPropertyChange(three.context) { name ->
|
||||
vision.onPropertyChange(three.context) { name, _ ->
|
||||
if (name.firstOrNull()?.body == REFERENCE_CHILD_PROPERTY_PREFIX) {
|
||||
val childName = name.firstOrNull()?.index?.let(Name::parse)
|
||||
?: error("Wrong syntax for reference child property: '$name'")
|
||||
|
||||
Reference in New Issue
Block a user