diff --git a/demo/js-playground/src/main/kotlin/JsPlaygroundApp.kt b/demo/js-playground/src/main/kotlin/JsPlaygroundApp.kt index edf159cd..ec28649c 100644 --- a/demo/js-playground/src/main/kotlin/JsPlaygroundApp.kt +++ b/demo/js-playground/src/main/kotlin/JsPlaygroundApp.kt @@ -1,7 +1,5 @@ import kotlinx.browser.document -import kotlinx.css.height -import kotlinx.css.pct -import kotlinx.css.width +import kotlinx.css.* import react.child import react.dom.render import space.kscience.dataforge.context.Context @@ -31,8 +29,10 @@ private class JsPlaygroundApp : Application { render(element) { styledDiv { css{ - height = 100.pct - width = 100.pct + padding(0.pt) + margin(0.pt) + height = 100.vh + width = 100.vw } child(ThreeCanvasWithControls) { attrs { diff --git a/visionforge-gdml/src/commonMain/kotlin/space/kscience/visionforge/gdml/GdmlOptimizer.kt b/visionforge-gdml/src/commonMain/kotlin/space/kscience/visionforge/gdml/GdmlOptimizer.kt index a35e845c..b2075e3a 100644 --- a/visionforge-gdml/src/commonMain/kotlin/space/kscience/visionforge/gdml/GdmlOptimizer.kt +++ b/visionforge-gdml/src/commonMain/kotlin/space/kscience/visionforge/gdml/GdmlOptimizer.kt @@ -11,22 +11,14 @@ public expect class Counter() { public fun incrementAndGet(): Int } -private fun Point3D?.safePlus(other: Point3D?): Point3D? = if (this == null && other == null) { - null -} else { - (this ?: Point3D(0, 0, 0)) + (other ?: Point3D(0, 0, 0)) -} - @DFExperimental internal fun Vision.updateFrom(other: Vision): Vision { if (this is Solid && other is Solid) { - position = position.safePlus(other.position) - rotation = rotation.safePlus(other.rotation) - if (this.scale != null || other.scale != null) { - scaleX = scaleX.toDouble() * other.scaleX.toDouble() - scaleY = scaleY.toDouble() * other.scaleY.toDouble() - scaleZ = scaleZ.toDouble() * other.scaleZ.toDouble() - } + position += other.position + rotation += other.rotation + scaleX = scaleX.toDouble() * other.scaleX.toDouble() + scaleY = scaleY.toDouble() * other.scaleY.toDouble() + scaleZ = scaleZ.toDouble() * other.scaleZ.toDouble() other.meta.itemSequence().forEach { (name, item) -> if (getProperty(name) == null) { setProperty(name, item) 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 9855c835..f2b14f2a 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 @@ -1,9 +1,7 @@ package space.kscience.visionforge.solid -import space.kscience.dataforge.meta.boolean +import space.kscience.dataforge.meta.* import space.kscience.dataforge.meta.descriptors.NodeDescriptor -import space.kscience.dataforge.meta.enum -import space.kscience.dataforge.meta.int import space.kscience.dataforge.names.Name import space.kscience.dataforge.names.asName import space.kscience.dataforge.names.plus @@ -14,15 +12,28 @@ import space.kscience.visionforge.Vision.Companion.VISIBLE_KEY import space.kscience.visionforge.solid.Solid.Companion.DETAIL_KEY import space.kscience.visionforge.solid.Solid.Companion.IGNORE_KEY import space.kscience.visionforge.solid.Solid.Companion.LAYER_KEY +import space.kscience.visionforge.solid.Solid.Companion.POSITION_KEY +import space.kscience.visionforge.solid.Solid.Companion.ROTATION_KEY +import space.kscience.visionforge.solid.Solid.Companion.SCALE_KEY +import space.kscience.visionforge.solid.Solid.Companion.X_KEY +import space.kscience.visionforge.solid.Solid.Companion.X_POSITION_KEY +import space.kscience.visionforge.solid.Solid.Companion.X_ROTATION_KEY +import space.kscience.visionforge.solid.Solid.Companion.X_SCALE_KEY +import space.kscience.visionforge.solid.Solid.Companion.Y_KEY +import space.kscience.visionforge.solid.Solid.Companion.Y_POSITION_KEY +import space.kscience.visionforge.solid.Solid.Companion.Y_ROTATION_KEY +import space.kscience.visionforge.solid.Solid.Companion.Y_SCALE_KEY +import space.kscience.visionforge.solid.Solid.Companion.Z_KEY +import space.kscience.visionforge.solid.Solid.Companion.Z_POSITION_KEY +import space.kscience.visionforge.solid.Solid.Companion.Z_ROTATION_KEY +import space.kscience.visionforge.solid.Solid.Companion.Z_SCALE_KEY +import kotlin.properties.ReadWriteProperty +import kotlin.reflect.KProperty /** * Interface for 3-dimensional [Vision] */ public interface Solid : Vision { - public var position: Point3D? - public var rotation: Point3D? - public var scale: Point3D? - override val descriptor: NodeDescriptor get() = Companion.descriptor public companion object { @@ -72,7 +83,7 @@ public interface Solid : Vision { hide() } - value(DETAIL_KEY){ + value(DETAIL_KEY) { type(ValueType.NUMBER) hide() } @@ -84,22 +95,6 @@ public interface Solid : Vision { } } } - - internal fun solidEquals(first: Solid, second: Solid): Boolean { - if (first.position != second.position) return false - if (first.rotation != second.rotation) return false - if (first.scale != second.scale) return false - if (first.meta != second.meta) return false - return true - } - - internal fun solidHashCode(solid: Solid): Int { - var result = +(solid.position?.hashCode() ?: 0) - result = 31 * result + (solid.rotation?.hashCode() ?: 0) - result = 31 * result + (solid.scale?.hashCode() ?: 0) - result = 31 * result + solid.allProperties().hashCode() - return result - } } } @@ -150,74 +145,44 @@ public var Vision.ignore: Boolean? // get() = getProperty(SELECTED_KEY).boolean // set(value) = setProperty(SELECTED_KEY, value) -private fun Solid.position(): Point3D = - position ?: Point3D(0.0, 0.0, 0.0).also { position = it } +internal fun number(name: Name, default: Number): ReadWriteProperty = + object : ReadWriteProperty { + override fun getValue(thisRef: Solid, property: KProperty<*>): Number { + return thisRef.getOwnProperty(name)?.number ?: default + } -public var Solid.x: Number - get() = position?.x ?: 0f - set(value) { - position().x = value.toFloat() - invalidateProperty(Solid.X_POSITION_KEY) + override fun setValue(thisRef: Solid, property: KProperty<*>, value: Number) { + thisRef.setProperty(name, value) + } } -public var Solid.y: Number - get() = position?.y ?: 0f - set(value) { - position().y = value.toFloat() - invalidateProperty(Solid.Y_POSITION_KEY) +internal fun point(name: Name, default: Float): ReadWriteProperty = + object : ReadWriteProperty { + override fun getValue(thisRef: Solid, property: KProperty<*>): Point3D = object : Point3D { + override val x: Float get() = thisRef.getOwnProperty(name + X_KEY)?.float ?: default + override val y: Float get() = thisRef.getOwnProperty(name + Y_KEY)?.float ?: default + override val z: Float get() = thisRef.getOwnProperty(name + Z_KEY)?.float ?: default + } + + override fun setValue(thisRef: Solid, property: KProperty<*>, value: Point3D) { + thisRef.setProperty(name + X_KEY, value.x) + thisRef.setProperty(name + Y_KEY, value.y) + thisRef.setProperty(name + Z_KEY, value.z) + } } -public var Solid.z: Number - get() = position?.z ?: 0f - set(value) { - position().z = value.toFloat() - invalidateProperty(Solid.Z_POSITION_KEY) - } +public var Solid.position: Point3D by point(POSITION_KEY, 0f) +public var Solid.rotation: Point3D by point(ROTATION_KEY, 0f) +public var Solid.scale: Point3D by point(SCALE_KEY, 1f) -private fun Solid.rotation(): Point3D = - rotation ?: Point3D(0.0, 0.0, 0.0).also { rotation = it } +public var Solid.x: Number by number(X_POSITION_KEY, 0f) +public var Solid.y: Number by number(Y_POSITION_KEY, 0f) +public var Solid.z: Number by number(Z_POSITION_KEY, 0f) -public var Solid.rotationX: Number - get() = rotation?.x ?: 0f - set(value) { - rotation().x = value.toFloat() - invalidateProperty(Solid.X_ROTATION_KEY) - } +public var Solid.rotationX: Number by number(X_ROTATION_KEY, 0f) +public var Solid.rotationY: Number by number(Y_ROTATION_KEY, 0f) +public var Solid.rotationZ: Number by number(Z_ROTATION_KEY, 0f) -public var Solid.rotationY: Number - get() = rotation?.y ?: 0f - set(value) { - rotation().y = value.toFloat() - invalidateProperty(Solid.Y_ROTATION_KEY) - } - -public var Solid.rotationZ: Number - get() = rotation?.z ?: 0f - set(value) { - rotation().z = value.toFloat() - invalidateProperty(Solid.Z_ROTATION_KEY) - } - -private fun Solid.scale(): Point3D = - scale ?: Point3D(1.0, 1.0, 1.0).also { scale = it } - -public var Solid.scaleX: Number - get() = scale?.x ?: 1f - set(value) { - scale().x = value.toFloat() - invalidateProperty(Solid.X_SCALE_KEY) - } - -public var Solid.scaleY: Number - get() = scale?.y ?: 1f - set(value) { - scale().y = value.toFloat() - invalidateProperty(Solid.Y_SCALE_KEY) - } - -public var Solid.scaleZ: Number - get() = scale?.z ?: 1f - set(value) { - scale().z = value.toFloat() - invalidateProperty(Solid.Z_SCALE_KEY) - } \ No newline at end of file +public var Solid.scaleX: Number by number(X_SCALE_KEY, 1f) +public var Solid.scaleY: Number by number(Y_SCALE_KEY, 1f) +public var Solid.scaleZ: Number by number(Z_SCALE_KEY, 1f) \ No newline at end of file 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 e69f729c..1f86bdb3 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 @@ -13,9 +13,9 @@ import space.kscience.visionforge.VisionChange @Serializable @SerialName("solid") public open class SolidBase( - override var position: Point3D? = null, - override var rotation: Point3D? = null, - override var scale: Point3D? = null, +// override var position: Point3D? = null, +// override var rotation: Point3D? = null, +// override var scale: Point3D? = null, ) : VisionBase(), Solid { override val descriptor: NodeDescriptor get() = Solid.descriptor diff --git a/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/SolidGroup.kt b/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/SolidGroup.kt index 20ca8afc..ad2107f0 100644 --- a/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/SolidGroup.kt +++ b/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/SolidGroup.kt @@ -29,9 +29,9 @@ public interface PrototypeHolder { @SerialName("group.solid") public class SolidGroup( @Serializable(PrototypeSerializer::class) internal var prototypes: MutableVisionGroup? = null, - override var position: Point3D? = null, - override var rotation: Point3D? = null, - override var scale: Point3D? = null, +// override var position: Point3D? = null, +// override var rotation: Point3D? = null, +// override var scale: Point3D? = null, ) : VisionGroupBase(), Solid, PrototypeHolder { init { diff --git a/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/SolidReference.kt b/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/SolidReference.kt index 17ee9141..3d067a62 100644 --- a/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/SolidReference.kt +++ b/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/SolidReference.kt @@ -96,22 +96,22 @@ public class SolidReferenceGroup( */ private inner class ReferenceChild(private val childName: Name) : SolidReference, VisionGroup { - //TODO replace by properties - override var position: Point3D? - get() = prototype.position - set(_) { - error("Can't set position of reference") - } - override var rotation: Point3D? - get() = prototype.rotation - set(_) { - error("Can't set position of reference") - } - override var scale: Point3D? - get() = prototype.scale - set(_) { - error("Can't set position of reference") - } +// //TODO replace by properties +// override var position: Point3D? +// get() = prototype.position +// set(_) { +// error("Can't set position of reference") +// } +// override var rotation: Point3D? +// get() = prototype.rotation +// set(_) { +// error("Can't set position of reference") +// } +// override var scale: Point3D? +// get() = prototype.scale +// set(_) { +// error("Can't set position of reference") +// } override val prototype: Solid get() = prototypeFor(childName) override val children: Map 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 28a90398..e8813779 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 @@ -1,10 +1,14 @@ package space.kscience.visionforge.solid +import kotlinx.serialization.KSerializer import kotlinx.serialization.Serializable -import space.kscience.dataforge.meta.Meta -import space.kscience.dataforge.meta.MetaBuilder -import space.kscience.dataforge.meta.float -import space.kscience.dataforge.meta.get +import kotlinx.serialization.descriptors.SerialDescriptor +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder +import space.kscience.dataforge.meta.* +import space.kscience.visionforge.solid.Solid.Companion.X_KEY +import space.kscience.visionforge.solid.Solid.Companion.Y_KEY +import space.kscience.visionforge.solid.Solid.Companion.Z_KEY import kotlin.math.PI import kotlin.math.pow import kotlin.math.sqrt @@ -17,25 +21,48 @@ public data class Point2D(public var x: Float, public var y: Float) public fun Point2D(x: Number, y: Number): Point2D = Point2D(x.toFloat(), y.toFloat()) public fun Point2D.toMeta(): Meta = Meta { - Solid.X_KEY put x - Solid.Y_KEY put y + X_KEY put x + Y_KEY put y } internal fun Meta.point2D(): Point2D = Point2D(this["x"].float ?: 0f, this["y"].float ?: 0f) -@Serializable -public data class Point3D( - public var x: Float, - public var y: Float, - public var z: Float, -) { +@Serializable(Point3DSerializer::class) +public interface Point3D { + public val x: Float + public val y: Float + public val z: Float + public companion object { public val ZERO: Point3D = Point3D(0.0, 0.0, 0.0) public val ONE: Point3D = Point3D(1.0, 1.0, 1.0) } } -public fun Point3D(x: Number, y: Number, z: Number): Point3D = Point3D(x.toFloat(), y.toFloat(), z.toFloat()) +@Serializable(Point3DSerializer::class) +public interface MutablePoint3D : Point3D { + override var x: Float + override var y: Float + override var z: Float +} + +@Serializable +private class Point3DImpl(override var x: Float, override var y: Float, override var z: Float) : MutablePoint3D + +internal object Point3DSerializer : KSerializer { + + override val descriptor: SerialDescriptor = Point3DImpl.serializer().descriptor + + + override fun deserialize(decoder: Decoder): Point3D = decoder.decodeSerializableValue(Point3DImpl.serializer()) + + override fun serialize(encoder: Encoder, value: Point3D) { + val impl: Point3DImpl = (value as? Point3DImpl) ?: Point3DImpl(value.x, value.y, value.z) + encoder.encodeSerializableValue(Point3DImpl.serializer(), impl) + } +} + +public fun Point3D(x: Number, y: Number, z: Number): Point3D = Point3DImpl(x.toFloat(), y.toFloat(), z.toFloat()) public operator fun Point3D.plus(other: Point3D): Point3D = Point3D( this.x + other.x, @@ -61,17 +88,21 @@ public infix fun Point3D.cross(other: Point3D): Point3D = Point3D( x * other.y - y * other.x ) -public fun Point3D.normalizeInPlace(){ +public fun MutablePoint3D.normalizeInPlace() { val norm = sqrt(x.pow(2) + y.pow(2) + z.pow(2)) x /= norm y /= norm z /= norm } -internal fun Meta.point3D() = Point3D(this["x"].float ?: 0.0, this["y"].float ?: 0.0, this["y"].float ?: 0.0) +internal fun ItemProvider.point3D(default: Float = 0f) = object : Point3D { + override val x: Float by float(default) + override val y: Float by float(default) + override val z: Float by float(default) +} public fun Point3D.toMeta(): MetaBuilder = Meta { - Solid.X_KEY put x - Solid.Y_KEY put y - Solid.Z_KEY put z + X_KEY put x + Y_KEY put y + Z_KEY put z } \ No newline at end of file diff --git a/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/transform/RemoveSingleChild.kt b/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/transform/RemoveSingleChild.kt index 5d07303e..c0c02bc7 100644 --- a/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/transform/RemoveSingleChild.kt +++ b/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/transform/RemoveSingleChild.kt @@ -14,18 +14,14 @@ internal fun mergeChild(parent: VisionGroup, child: Vision): Vision { //parent.properties?.let { config.update(it) } if (this is Solid && parent is Solid) { - position = (position ?: Point3D.ZERO) + (parent.position ?: Point3D.ZERO) - rotation = (parent.rotation ?: Point3D.ZERO) + (parent.rotation ?: Point3D.ZERO) - scale = when { - scale == null && parent.scale == null -> null - scale == null -> parent.scale - parent.scale == null -> scale - else -> Point3D( - scale!!.x * parent.scale!!.x, - scale!!.y * parent.scale!!.y, - scale!!.z * parent.scale!!.z - ) - } + position += parent.position + rotation += parent.rotation + scale = Point3D( + scale.x * parent.scale.x, + scale.y * parent.scale.y, + scale.z * parent.scale.z + ) + } } diff --git a/visionforge-threejs/src/main/kotlin/info/laht/threekt/animation/AnimationAction.kt b/visionforge-threejs/src/main/kotlin/info/laht/threekt/animation/AnimationAction.kt index 8abbc8ae..d0e9b073 100644 --- a/visionforge-threejs/src/main/kotlin/info/laht/threekt/animation/AnimationAction.kt +++ b/visionforge-threejs/src/main/kotlin/info/laht/threekt/animation/AnimationAction.kt @@ -1,3 +1,4 @@ +@file:Suppress("NO_EXPLICIT_VISIBILITY_IN_API_MODE_WARNING", "unused") @file:JsModule("three") @file:JsNonModule