diff --git a/CHANGELOG.md b/CHANGELOG.md index 8ea6fc9b..aff57288 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,8 @@ - VisionGroup builder accepts `null` as name for statics instead of `""` - gdml sphere is rendered as a SphereLayer instead of Sphere (#35) - Tube is replaced by more general ConeSurface +- position, rotation and size moved to properties +- prototypes moved to children ### Deprecated diff --git a/demo/solid-showcase/src/commonMain/kotlin/space/kscience/visionforge/solid/demo/demo.kt b/demo/solid-showcase/src/commonMain/kotlin/space/kscience/visionforge/solid/demo/demo.kt index bfa90827..2385fef1 100644 --- a/demo/solid-showcase/src/commonMain/kotlin/space/kscience/visionforge/solid/demo/demo.kt +++ b/demo/solid-showcase/src/commonMain/kotlin/space/kscience/visionforge/solid/demo/demo.kt @@ -27,7 +27,7 @@ fun VisionLayout.demo(name: String, title: String = name, block: SolidGro } val canvasOptions = Canvas3DOptions { - size{ + size { minSize = 400 } axes { @@ -57,9 +57,8 @@ fun VisionLayout.showcase() { rotationX = PI / 4 color("blue") } - sphereLayer(50,40){ - theta = (PI/2).toFloat() - rotationX = - PI * 3 / 4 + sphereLayer(50, 40, theta = PI / 2) { + rotationX = -PI * 3 / 4 z = 110 color(Colors.pink) } 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 f372fa38..22cac2c6 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 @@ -23,7 +23,7 @@ internal fun SolidGroup.varBox( action: VariableBox.() -> Unit = {}, ): VariableBox = VariableBox(xSize, ySize).apply(action).also { set(name, it) } -internal class VariableBox(val xSize: Number, val ySize: Number) : ThreeVision() { +internal class VariableBox(val xSize: Number, val ySize: Number) : ThreeJsVision() { override fun render(three: ThreePlugin): Object3D { val geometry = BoxGeometry(xSize, ySize, 1) diff --git a/visionforge-core/src/commonMain/kotlin/space/kscience/visionforge/VisionPropertyContainer.kt b/visionforge-core/src/commonMain/kotlin/space/kscience/visionforge/VisionPropertyContainer.kt index 68567ee3..112295c9 100644 --- a/visionforge-core/src/commonMain/kotlin/space/kscience/visionforge/VisionPropertyContainer.kt +++ b/visionforge-core/src/commonMain/kotlin/space/kscience/visionforge/VisionPropertyContainer.kt @@ -1,12 +1,15 @@ package space.kscience.visionforge +import space.kscience.dataforge.meta.Config import space.kscience.dataforge.meta.MetaItem +import space.kscience.dataforge.meta.get +import space.kscience.dataforge.meta.set import space.kscience.dataforge.names.Name /** * Property containers are used to create a symmetric behaviors for vision properties and style builders */ -public interface VisionPropertyContainer { +public interface VisionPropertyContainer { public fun getProperty( name: Name, inherit: Boolean = false, @@ -15,4 +18,18 @@ public interface VisionPropertyContainer { ): MetaItem? public fun setProperty(name: Name, item: MetaItem?, notify: Boolean = true) +} + +public open class SimpleVisionPropertyContainer(protected val config: Config): VisionPropertyContainer{ + override fun getProperty( + name: Name, + inherit: Boolean, + includeStyles: Boolean, + includeDefaults: Boolean + ): MetaItem? = config[name] + + override fun setProperty(name: Name, item: MetaItem?, notify: Boolean) { + config[name] = item + } + } \ No newline at end of file diff --git a/visionforge-gdml/src/commonMain/kotlin/space/kscience/visionforge/gdml/GdmlTransformer.kt b/visionforge-gdml/src/commonMain/kotlin/space/kscience/visionforge/gdml/GdmlTransformer.kt index 3a7b48af..98b4509e 100644 --- a/visionforge-gdml/src/commonMain/kotlin/space/kscience/visionforge/gdml/GdmlTransformer.kt +++ b/visionforge-gdml/src/commonMain/kotlin/space/kscience/visionforge/gdml/GdmlTransformer.kt @@ -232,11 +232,10 @@ private class GdmlTransformerEnv(val settings: GdmlTransformer) { bottomRadius = solid.rmax1 * lScale, height = solid.z * lScale, upperRadius = solid.rmax2 * lScale, + startAngle = solid.startphi * aScale, + angle = solid.deltaphi * aScale, name = name - ) { - startAngle = solid.startphi * aScale - angle = solid.deltaphi * aScale - } + ) } else { coneSurface( bottomOuterRadius = solid.rmax1 * lScale, @@ -244,11 +243,10 @@ private class GdmlTransformerEnv(val settings: GdmlTransformer) { height = solid.z * lScale, topOuterRadius = solid.rmax2 * lScale, topInnerRadius = solid.rmin2 * lScale, + startAngle = solid.startphi * aScale, + angle = solid.deltaphi * aScale, name = name - ) { - startAngle = solid.startphi * aScale - angle = solid.deltaphi * aScale - } + ) } is GdmlXtru -> extrude(name) { shape { @@ -276,12 +274,15 @@ private class GdmlTransformerEnv(val settings: GdmlTransformer) { scaleZ = solid.scale.z.toFloat() } } - is GdmlSphere -> sphereLayer(solid.rmax * lScale, solid.rmin * lScale, name) { - phi = solid.deltaphi * aScale - theta = solid.deltatheta * aScale - phiStart = solid.startphi * aScale - thetaStart = solid.starttheta * aScale - } + is GdmlSphere -> sphereLayer( + outerRadius = solid.rmax * lScale, + innerRadius = solid.rmin * lScale, + phi = solid.deltaphi * aScale, + theta = solid.deltatheta * aScale, + phiStart = solid.startphi * aScale, + thetaStart = solid.starttheta * aScale, + name = name, + ) is GdmlOrb -> sphere(solid.r * lScale, name = name) is GdmlPolyhedra -> extrude(name) { //getting the radius of first diff --git a/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/ConeSegment.kt b/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/ConeSegment.kt index 211e3af2..560ec496 100644 --- a/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/ConeSegment.kt +++ b/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/ConeSegment.kt @@ -15,11 +15,11 @@ import kotlin.math.sin @Serializable @SerialName("solid.cone") public class ConeSegment( - public var bottomRadius: Float, - public var height: Float, - public var topRadius: Float, - public var startAngle: Float = 0f, - public var angle: Float = PI2 + public val bottomRadius: Float, + public val height: Float, + public val topRadius: Float, + public val startAngle: Float = 0f, + public val angle: Float = PI2 ) : SolidBase(), GeometrySolid { override fun toGeometry(geometryBuilder: GeometryBuilder) { @@ -83,10 +83,14 @@ public inline fun VisionContainerBuilder.cone( bottomRadius: Number, height: Number, upperRadius: Number = 0.0, + startAngle: Number = 0f, + angle: Number = PI2, name: String? = null, block: ConeSegment.() -> Unit = {} ): ConeSegment = ConeSegment( bottomRadius.toFloat(), height.toFloat(), - topRadius = upperRadius.toFloat() + topRadius = upperRadius.toFloat(), + startAngle = startAngle.toFloat(), + angle = angle.toFloat() ).apply(block).also { set(name, it) } \ No newline at end of file diff --git a/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/ConeSurface.kt b/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/ConeSurface.kt index caa8c746..a9c5622b 100644 --- a/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/ConeSurface.kt +++ b/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/ConeSurface.kt @@ -16,13 +16,13 @@ import kotlin.math.sin @Serializable @SerialName("solid.coneSurface") public class ConeSurface( - public var bottomRadius: Float, - public var bottomInnerRadius: Float, - public var height: Float, - public var topRadius: Float, - public var topInnerRadius: Float, - public var startAngle: Float = 0f, - public var angle: Float = PI2, + public val bottomRadius: Float, + public val bottomInnerRadius: Float, + public val height: Float, + public val topRadius: Float, + public val topInnerRadius: Float, + public val startAngle: Float = 0f, + public val angle: Float = PI2, ) : SolidBase(), GeometrySolid { init { @@ -148,6 +148,8 @@ public inline fun VisionContainerBuilder.coneSurface( height: Number, topOuterRadius: Number, topInnerRadius: Number, + startAngle: Number = 0f, + angle: Number = PI2, name: String? = null, block: ConeSurface.() -> Unit = {}, ): ConeSurface = ConeSurface( @@ -156,4 +158,6 @@ public inline fun VisionContainerBuilder.coneSurface( height = height.toFloat(), topRadius = topOuterRadius.toFloat(), topInnerRadius = topInnerRadius.toFloat(), + startAngle = startAngle.toFloat(), + angle = angle.toFloat() ).apply(block).also { set(name, it) } \ No newline at end of file diff --git a/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/Extruded.kt b/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/Extruded.kt index d5943e3a..40e03512 100644 --- a/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/Extruded.kt +++ b/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/Extruded.kt @@ -2,9 +2,8 @@ package space.kscience.visionforge.solid import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable -import space.kscience.visionforge.VisionBuilder -import space.kscience.visionforge.VisionContainerBuilder -import space.kscience.visionforge.set +import space.kscience.dataforge.meta.Config +import space.kscience.visionforge.* import kotlin.math.PI import kotlin.math.cos import kotlin.math.sin @@ -13,7 +12,7 @@ import kotlin.math.sin public typealias Shape2D = List @Serializable -public class Shape2DBuilder(private val points: MutableList = ArrayList()) { +public class Shape2DBuilder(private val points: ArrayList = ArrayList()) { public fun point(x: Number, y: Number) { points.add(Point2D(x, y)) @@ -38,19 +37,9 @@ public data class Layer(var x: Float, var y: Float, var z: Float, var scale: Flo @Serializable @SerialName("solid.extrude") public class Extruded( - public var shape: List = ArrayList(), - public var layers: MutableList = ArrayList() -) : SolidBase(), GeometrySolid { - - public fun shape(block: Shape2DBuilder.() -> Unit) { - this.shape = Shape2DBuilder().apply(block).build() - //TODO send invalidation signal - } - - public fun layer(z: Number, x: Number = 0.0, y: Number = 0.0, scale: Number = 1.0) { - layers.add(Layer(x.toFloat(), y.toFloat(), z.toFloat(), scale.toFloat())) - //TODO send invalidation signal - } + public val shape: List, + public val layers: List +) : SolidBase(), GeometrySolid, VisionPropertyContainer { override fun toGeometry(geometryBuilder: GeometryBuilder) { val shape: Shape2D = shape @@ -103,6 +92,24 @@ public class Extruded( } } +public class ExtrudeBuilder( + public var shape: List = emptyList(), + public var layers: ArrayList = ArrayList(), + config: Config = Config() +) : SimpleVisionPropertyContainer(config) { + public fun shape(block: Shape2DBuilder.() -> Unit) { + this.shape = Shape2DBuilder().apply(block).build() + } + + public fun layer(z: Number, x: Number = 0.0, y: Number = 0.0, scale: Number = 1.0) { + layers.add(Layer(x.toFloat(), y.toFloat(), z.toFloat(), scale.toFloat())) + } + + internal fun build(): Extruded = Extruded(shape, layers).apply { configure(config) } +} + @VisionBuilder -public fun VisionContainerBuilder.extrude(name: String? = null, action: Extruded.() -> Unit = {}): Extruded = - Extruded().apply(action).also { set(name, it) } \ No newline at end of file +public fun VisionContainerBuilder.extrude( + name: String? = null, + action: ExtrudeBuilder.() -> Unit = {} +): Extruded = ExtrudeBuilder().apply(action).build().also { set(name, it) } \ No newline at end of file diff --git a/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/PolyLine.kt b/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/PolyLine.kt index 41fe9903..cd9f2cbd 100644 --- a/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/PolyLine.kt +++ b/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/PolyLine.kt @@ -13,7 +13,7 @@ import space.kscience.visionforge.set @Serializable @SerialName("solid.line") -public class PolyLine(public var points: List) : SolidBase(), Solid { +public class PolyLine(public val points: List) : SolidBase(), Solid { //var lineType by string() public var thickness: Number by allProperties(inherit = false).number(1.0, diff --git a/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/Solid.kt b/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/Solid.kt index a4c8e69c..0a59d141 100644 --- a/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/Solid.kt +++ b/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/Solid.kt @@ -37,6 +37,8 @@ public interface Solid : Vision { override val descriptor: NodeDescriptor get() = Companion.descriptor + + public companion object { // val SELECTED_KEY = "selected".asName() public val DETAIL_KEY: Name = "detail".asName() diff --git a/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/SolidBase.kt b/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/SolidBase.kt index c88052b2..d2fee33a 100644 --- a/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/SolidBase.kt +++ b/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/SolidBase.kt @@ -2,11 +2,7 @@ package space.kscience.visionforge.solid import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable -import space.kscience.dataforge.meta.Meta import space.kscience.dataforge.meta.descriptors.NodeDescriptor -import space.kscience.dataforge.meta.float -import space.kscience.dataforge.meta.get -import space.kscience.dataforge.meta.node import space.kscience.visionforge.VisionBase import space.kscience.visionforge.VisionChange @@ -20,15 +16,3 @@ public open class SolidBase : VisionBase(), Solid { super.update(change) } } - -internal fun Meta.toVector(default: Float = 0f) = Point3D( - this[Solid.X_KEY].float ?: default, - this[Solid.Y_KEY].float ?: default, - this[Solid.Z_KEY].float ?: default -) - -internal fun Solid.updatePosition(meta: Meta?) { - meta[Solid.POSITION_KEY].node?.toVector()?.let { position = it } - meta[Solid.ROTATION_KEY].node?.toVector()?.let { rotation = it } - meta[Solid.SCALE_KEY].node?.toVector(1f)?.let { scale = it } -} \ No newline at end of file diff --git a/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/SolidLabel.kt b/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/SolidLabel.kt index ac45e22e..3e725d0d 100644 --- a/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/SolidLabel.kt +++ b/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/SolidLabel.kt @@ -9,9 +9,9 @@ import space.kscience.visionforge.set @Serializable @SerialName("solid.label") public class SolidLabel( - public var text: String, - public var fontSize: Double, - public var fontFamily: String, + public val text: String, + public val fontSize: Double, + public val fontFamily: String, ) : SolidBase(), Solid @VisionBuilder diff --git a/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/Sphere.kt b/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/Sphere.kt index c4d67f97..a6af3cd8 100644 --- a/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/Sphere.kt +++ b/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/Sphere.kt @@ -4,6 +4,7 @@ import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable import space.kscience.visionforge.VisionBuilder import space.kscience.visionforge.VisionContainerBuilder +import space.kscience.visionforge.VisionPropertyContainer import space.kscience.visionforge.set import kotlin.math.PI import kotlin.math.cos @@ -12,12 +13,12 @@ import kotlin.math.sin @Serializable @SerialName("solid.sphere") public class Sphere( - public var radius: Float, - public var phiStart: Float = 0f, - public var phi: Float = PI2, - public var thetaStart: Float = 0f, - public var theta: Float = PI.toFloat(), -) : SolidBase(), GeometrySolid { + public val radius: Float, + public val phiStart: Float = 0f, + public val phi: Float = PI2, + public val thetaStart: Float = 0f, + public val theta: Float = PI.toFloat(), +) : SolidBase(), GeometrySolid, VisionPropertyContainer { override fun toGeometry(geometryBuilder: GeometryBuilder) { fun point3DfromSphCoord(r: Float, theta: Float, phi: Float): Point3D { diff --git a/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/SphereLayer.kt b/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/SphereLayer.kt index 83e358e2..05149e2e 100644 --- a/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/SphereLayer.kt +++ b/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/SphereLayer.kt @@ -15,12 +15,12 @@ import kotlin.math.sin @Serializable @SerialName("solid.sphereLayer") public class SphereLayer( - public var outerRadius: Float, - public var innerRadius: Float, - public var phiStart: Float = 0f, - public var phi: Float = PI2, - public var thetaStart: Float = 0f, - public var theta: Float = PI.toFloat(), + public val outerRadius: Float, + public val innerRadius: Float, + public val phiStart: Float = 0f, + public val phi: Float = PI2, + public val thetaStart: Float = 0f, + public val theta: Float = PI.toFloat(), ) : SolidBase(), GeometrySolid { override fun toGeometry(geometryBuilder: GeometryBuilder): Unit = geometryBuilder.run { @@ -72,9 +72,17 @@ public class SphereLayer( public inline fun VisionContainerBuilder.sphereLayer( outerRadius: Number, innerRadius: Number, + phiStart: Number = 0f, + phi: Number = PI2, + thetaStart: Number = 0f, + theta: Number = PI.toFloat(), name: String? = null, action: SphereLayer.() -> Unit = {}, ): SphereLayer = SphereLayer( outerRadius.toFloat(), innerRadius.toFloat(), + phiStart.toFloat(), + phi.toFloat(), + thetaStart.toFloat(), + theta.toFloat() ).apply(action).also { set(name, it) } \ No newline at end of file diff --git a/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/geometry.kt b/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/geometry.kt index e8813779..f5aa2d4a 100644 --- a/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/geometry.kt +++ b/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/geometry.kt @@ -105,4 +105,17 @@ public fun Point3D.toMeta(): MetaBuilder = Meta { X_KEY put x Y_KEY put y Z_KEY put z +} + + +internal fun Meta.toVector(default: Float = 0f) = Point3D( + this[Solid.X_KEY].float ?: default, + this[Solid.Y_KEY].float ?: default, + this[Solid.Z_KEY].float ?: default +) + +internal fun Solid.updatePosition(meta: Meta?) { + meta[Solid.POSITION_KEY].node?.toVector()?.let { position = it } + meta[Solid.ROTATION_KEY].node?.toVector()?.let { rotation = it } + meta[Solid.SCALE_KEY].node?.toVector(1f)?.let { scale = it } } \ No newline at end of file diff --git a/visionforge-threejs/src/main/kotlin/space/kscience/visionforge/solid/three/ThreeVision.kt b/visionforge-threejs/src/main/kotlin/space/kscience/visionforge/solid/three/ThreeJsVision.kt similarity index 83% rename from visionforge-threejs/src/main/kotlin/space/kscience/visionforge/solid/three/ThreeVision.kt rename to visionforge-threejs/src/main/kotlin/space/kscience/visionforge/solid/three/ThreeJsVision.kt index 16d1bd4f..27a5da44 100644 --- a/visionforge-threejs/src/main/kotlin/space/kscience/visionforge/solid/three/ThreeVision.kt +++ b/visionforge-threejs/src/main/kotlin/space/kscience/visionforge/solid/three/ThreeJsVision.kt @@ -6,6 +6,6 @@ import space.kscience.visionforge.solid.SolidBase /** * A custom visual object that has its own Three.js renderer */ -public abstract class ThreeVision : SolidBase() { +public abstract class ThreeJsVision : SolidBase() { public abstract fun render(three: ThreePlugin): Object3D } diff --git a/visionforge-threejs/src/main/kotlin/space/kscience/visionforge/solid/three/ThreePlugin.kt b/visionforge-threejs/src/main/kotlin/space/kscience/visionforge/solid/three/ThreePlugin.kt index 68fa692a..e6d85dc5 100644 --- a/visionforge-threejs/src/main/kotlin/space/kscience/visionforge/solid/three/ThreePlugin.kt +++ b/visionforge-threejs/src/main/kotlin/space/kscience/visionforge/solid/three/ThreePlugin.kt @@ -49,7 +49,7 @@ public class ThreePlugin : AbstractPlugin(), ElementVisionRenderer { } public fun buildObject3D(obj: Solid): Object3D = when (obj) { - is ThreeVision -> obj.render(this) + is ThreeJsVision -> obj.render(this) is SolidReferenceGroup -> ThreeReferenceFactory(this, obj) is SolidGroup -> { val group = ThreeGroup()