diff --git a/CHANGELOG.md b/CHANGELOG.md index f60db403..2b7d7766 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ - MeshLine for thick lines ### Changed +- Edges moved to solids module for easier construction - Visions **must** be rooted in order to subscribe to updates. - Visions use flows instead of direct subscriptions. - Radical change of inner workings of vision children and properties. diff --git a/demo/solid-showcase/src/jsMain/kotlin/space/kscience/visionforge/solid/demo/VariableBox.kt b/demo/solid-showcase/src/jsMain/kotlin/space/kscience/visionforge/solid/demo/VariableBox.kt index 1e626155..15e53129 100644 --- a/demo/solid-showcase/src/jsMain/kotlin/space/kscience/visionforge/solid/demo/VariableBox.kt +++ b/demo/solid-showcase/src/jsMain/kotlin/space/kscience/visionforge/solid/demo/VariableBox.kt @@ -8,6 +8,7 @@ import space.kscience.dataforge.names.startsWith import space.kscience.visionforge.onPropertyChange import space.kscience.visionforge.setChild import space.kscience.visionforge.solid.SolidGroup +import space.kscience.visionforge.solid.SolidMaterial.Companion.EDGES_KEY import space.kscience.visionforge.solid.layer import space.kscience.visionforge.solid.three.* import three.core.Object3D @@ -60,7 +61,7 @@ internal class VariableBox(val xSize: Number, val ySize: Number) : ThreeJsVision mesh.updateMatrix() } - name.startsWith(ThreeMeshFactory.EDGES_KEY) -> mesh.applyEdges(this@VariableBox) + name.startsWith(EDGES_KEY) -> mesh.applyEdges(this@VariableBox) else -> mesh.updateProperty(this@VariableBox, name) } } diff --git a/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/SolidMaterial.kt b/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/SolidMaterial.kt index 7d5c4d00..df720e6c 100644 --- a/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/SolidMaterial.kt +++ b/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/SolidMaterial.kt @@ -52,6 +52,11 @@ public class SolidMaterial : Scheme() { public val MATERIAL_SPECULAR_COLOR_KEY: Name = MATERIAL_KEY + SPECULAR_COLOR_KEY public val MATERIAL_WIREFRAME_KEY: Name = MATERIAL_KEY + WIREFRAME_KEY + public val EDGES_KEY: Name = "edges".asName() + public val ENABLED_KEY: Name = "enabled".asName() + public val EDGES_ENABLED_KEY: Name = EDGES_KEY + ENABLED_KEY + public val EDGES_MATERIAL_KEY: Name = EDGES_KEY + MATERIAL_KEY + public override val descriptor: MetaDescriptor by lazy { //must be lazy to avoid initialization bug MetaDescriptor { @@ -114,4 +119,11 @@ public var Solid.opacity: Number? get() = properties.getValue(MATERIAL_OPACITY_KEY, inherit = true)?.number set(value) { properties.setValue(MATERIAL_OPACITY_KEY, value?.asValue()) - } \ No newline at end of file + } + + +@VisionBuilder +public fun Solid.edges(enabled: Boolean = true, block: SolidMaterial.() -> Unit = {}) { + properties[SolidMaterial.EDGES_ENABLED_KEY] = enabled + SolidMaterial.write(properties.getProperty(SolidMaterial.EDGES_MATERIAL_KEY)).apply(block) +} \ No newline at end of file diff --git a/visionforge-threejs/src/main/kotlin/space/kscience/visionforge/solid/three/ThreeCompositeFactory.kt b/visionforge-threejs/src/main/kotlin/space/kscience/visionforge/solid/three/ThreeCompositeFactory.kt index 44bcb797..fe40022d 100644 --- a/visionforge-threejs/src/main/kotlin/space/kscience/visionforge/solid/three/ThreeCompositeFactory.kt +++ b/visionforge-threejs/src/main/kotlin/space/kscience/visionforge/solid/three/ThreeCompositeFactory.kt @@ -5,6 +5,7 @@ import space.kscience.dataforge.names.startsWith import space.kscience.visionforge.onPropertyChange import space.kscience.visionforge.solid.Composite import space.kscience.visionforge.solid.CompositeType +import space.kscience.visionforge.solid.SolidMaterial.Companion.EDGES_KEY import three.objects.Mesh import kotlin.reflect.KClass @@ -38,10 +39,10 @@ public class ThreeCompositeFactory(public val three: ThreePlugin) : ThreeFactory override val type: KClass get() = Composite::class override fun build(three: ThreePlugin, vision: Composite, observe: Boolean): Mesh { - val first = - three.buildObject3D(vision.first, observe).takeIfMesh() ?: error("First part of composite is not a mesh") - val second = - three.buildObject3D(vision.second, observe).takeIfMesh() ?: error("Second part of composite is not a mesh") + val first = three.buildObject3D(vision.first, observe).takeIfMesh() + ?: error("First part of composite is not a mesh") + val second = three.buildObject3D(vision.second, observe).takeIfMesh() + ?: error("Second part of composite is not a mesh") return when (vision.compositeType) { CompositeType.GROUP, CompositeType.UNION -> CSG.union(first, second) CompositeType.INTERSECT -> CSG.intersect(first, second) @@ -49,11 +50,12 @@ public class ThreeCompositeFactory(public val three: ThreePlugin) : ThreeFactory }.apply { updatePosition(vision) applyProperties(vision) + if (observe) { vision.onPropertyChange { name -> when { //name.startsWith(WIREFRAME_KEY) -> mesh.applyWireFrame(obj) - name.startsWith(ThreeMeshFactory.EDGES_KEY) -> applyEdges(vision) + name.startsWith(EDGES_KEY) -> applyEdges(vision) else -> updateProperty(vision, name) } } diff --git a/visionforge-threejs/src/main/kotlin/space/kscience/visionforge/solid/three/ThreeMeshFactory.kt b/visionforge-threejs/src/main/kotlin/space/kscience/visionforge/solid/three/ThreeMeshFactory.kt index b27bdcab..b3281e4b 100644 --- a/visionforge-threejs/src/main/kotlin/space/kscience/visionforge/solid/three/ThreeMeshFactory.kt +++ b/visionforge-threejs/src/main/kotlin/space/kscience/visionforge/solid/three/ThreeMeshFactory.kt @@ -1,18 +1,13 @@ package space.kscience.visionforge.solid.three import space.kscience.dataforge.meta.boolean -import space.kscience.dataforge.names.Name -import space.kscience.dataforge.names.asName -import space.kscience.dataforge.names.plus import space.kscience.dataforge.names.startsWith -import space.kscience.visionforge.VisionBuilder import space.kscience.visionforge.onPropertyChange -import space.kscience.visionforge.set import space.kscience.visionforge.solid.Solid -import space.kscience.visionforge.solid.SolidMaterial +import space.kscience.visionforge.solid.SolidMaterial.Companion.EDGES_ENABLED_KEY +import space.kscience.visionforge.solid.SolidMaterial.Companion.EDGES_KEY +import space.kscience.visionforge.solid.SolidMaterial.Companion.EDGES_MATERIAL_KEY import space.kscience.visionforge.solid.layer -import space.kscience.visionforge.solid.three.ThreeMeshFactory.Companion.EDGES_ENABLED_KEY -import space.kscience.visionforge.solid.three.ThreeMeshFactory.Companion.EDGES_MATERIAL_KEY import space.kscience.visionforge.solid.three.ThreeMeshFactory.Companion.EDGES_OBJECT_NAME import three.core.BufferGeometry import three.geometries.EdgesGeometry @@ -43,7 +38,7 @@ public abstract class ThreeMeshFactory( applyProperties(vision) } - if(observe) { + if (observe) { //add listener to object properties vision.onPropertyChange(three.context) { name -> when { @@ -66,24 +61,15 @@ public abstract class ThreeMeshFactory( } public companion object { - public val EDGES_KEY: Name = "edges".asName() internal const val EDGES_OBJECT_NAME: String = "@edges" //public val WIREFRAME_KEY: Name = "wireframe".asName() - public val ENABLED_KEY: Name = "enabled".asName() - public val EDGES_ENABLED_KEY: Name = EDGES_KEY + ENABLED_KEY - public val EDGES_MATERIAL_KEY: Name = EDGES_KEY + SolidMaterial.MATERIAL_KEY + //public val WIREFRAME_ENABLED_KEY: Name = WIREFRAME_KEY + ENABLED_KEY //public val WIREFRAME_MATERIAL_KEY: Name = WIREFRAME_KEY + SolidMaterial.MATERIAL_KEY } } -@VisionBuilder -public fun Solid.edges(enabled: Boolean = true, block: SolidMaterial.() -> Unit = {}) { - properties[EDGES_ENABLED_KEY] = enabled - SolidMaterial.write(properties.getProperty(EDGES_MATERIAL_KEY)).apply(block) -} - internal fun Mesh.applyProperties(vision: Solid): Mesh = apply { setMaterial(vision) applyEdges(vision) @@ -97,13 +83,12 @@ internal fun Mesh.applyProperties(vision: Solid): Mesh = apply { 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.properties.getValue(EDGES_ENABLED_KEY, inherit = true)?.boolean != false) { - val bufferGeometry = geometry as? BufferGeometry ?: return + if (vision.properties.getValue(EDGES_ENABLED_KEY, inherit = false)?.boolean != false) { val material = ThreeMaterials.getLineMaterial(vision.properties.getProperty(EDGES_MATERIAL_KEY), true) if (edges == null) { add( LineSegments( - EdgesGeometry(bufferGeometry), + EdgesGeometry(geometry), material ).apply { name = EDGES_OBJECT_NAME