Fix material display and useProperties

This commit is contained in:
2025-02-03 16:35:29 +03:00
parent 63a79a59cd
commit 5d5e284fe2
26 changed files with 156 additions and 90 deletions

View File

@@ -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)
}
}

View File

@@ -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 {

View File

@@ -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

View File

@@ -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)
/**

View File

@@ -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)

View File

@@ -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)
}
}
}

View File

@@ -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)
}

View File

@@ -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

View File

@@ -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)
}
}
}

View File

@@ -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
}

View File

@@ -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"]!!)
)
}
}

View File

@@ -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)
}
}

View File

@@ -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)
}
}

View File

@@ -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())
}
}
}

View File

@@ -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)

View File

@@ -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)
}
}

View File

@@ -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)

View File

@@ -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
}
}

View File

@@ -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" }
}

View File

@@ -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)
}
}

View File

@@ -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
}

View File

@@ -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(

View File

@@ -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)
}
}

View File

@@ -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" }

View File

@@ -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()

View File

@@ -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'")