Skip to content

Commit

Permalink
expression fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
Zhirkevich Alexander Y authored and Zhirkevich Alexander Y committed Jul 30, 2024
1 parent c972dbf commit 6ab2e59
Show file tree
Hide file tree
Showing 28 changed files with 582 additions and 2,035 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@ import androidx.compose.ui.graphics.Matrix
import io.github.alexzhirkevich.compottie.dynamic.DynamicTransformProvider
import io.github.alexzhirkevich.compottie.internal.AnimationState
import io.github.alexzhirkevich.compottie.internal.helpers.BooleanInt
import io.github.alexzhirkevich.compottie.internal.platform.ComposeBackend
import io.github.alexzhirkevich.compottie.internal.platform.currentComposeBackend
import io.github.alexzhirkevich.compottie.internal.utils.degreeToRadians
import io.github.alexzhirkevich.compottie.internal.utils.fastReset
import io.github.alexzhirkevich.compottie.internal.utils.preConcat
Expand Down Expand Up @@ -71,13 +69,12 @@ internal abstract class AnimatedTransform {
}

val interpolatedPosition = position.interpolated(state)
.takeIf { it != Vec2.Zero }
?.also {
.also {
matrix.preTranslate(it.x, it.y)
}

if (autoOrient){
if (interpolatedPosition != null) {
if (interpolatedPosition != Vec2.Zero) {
// Store the start X and Y values because the pointF will be overwritten by the next getValue call.
val startX = interpolatedPosition.x
val startY = interpolatedPosition.y
Expand Down Expand Up @@ -105,15 +102,13 @@ internal abstract class AnimatedTransform {
}
}

// if (currentComposeBackend != ComposeBackend.Android) {
rotationX?.let {
matrix.preRotateX(it.interpolated(state))
}
rotationX?.let {
matrix.preRotateX(it.interpolated(state))
}

rotationY?.let {
matrix.preRotateY(it.interpolated(state))
}
// }
rotationY?.let {
matrix.preRotateY(it.interpolated(state))
}

rotationZ?.let {
matrix.preRotateZ(it.interpolated(state))
Expand Down Expand Up @@ -164,14 +159,12 @@ internal abstract class AnimatedTransform {


scale.interpolatedNorm(state)
.takeIf { it.x != 1f || it.y != 1f }
?.let {
.let {
matrix.preScale(it.x, it.y)
}

anchorPoint.interpolated(state)
.takeIf { it != Vec2.Zero }
?.let {
.let {
matrix.preTranslate(-it.x, -it.y)
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package io.github.alexzhirkevich.compottie.internal.animation

import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.graphics.Matrix
import io.github.alexzhirkevich.compottie.internal.AnimationState
import io.github.alexzhirkevich.compottie.internal.utils.fastReset
Expand Down Expand Up @@ -44,15 +43,14 @@ internal class RepeaterTransform(
fun repeaterMatrix(state: AnimationState, amount: Float): Matrix {
matrix.fastReset()

position.interpolated(state).takeIf { it != Vec2.Zero }?.let {
position.interpolated(state).let {
matrix.preTranslate(
it.x * amount,
it.y * amount
)
}

scale.interpolatedNorm(state).takeIf { it.x != 1f || it.y != 1f }
?.let {
scale.interpolatedNorm(state).let {
matrix.preScale(
it.x.pow(amount),
it.y.pow(amount)
Expand All @@ -61,15 +59,9 @@ internal class RepeaterTransform(

rotation.interpolated(state).let {
val anchorPoint = anchorPoint.interpolated(state)

if (anchorPoint != Vec2.Zero) {
matrix.translate(anchorPoint.x, anchorPoint.y)
}
matrix.translate(anchorPoint.x, anchorPoint.y)
matrix.preRotate(it * amount)

if (anchorPoint != Vec2.Zero) {
matrix.translate(-anchorPoint.x, -anchorPoint.y)
}
matrix.translate(-anchorPoint.x, -anchorPoint.y)
}

return matrix
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
package io.github.alexzhirkevich.compottie.internal.animation.expressions.operations.composition

import androidx.compose.ui.util.fastMap
import io.github.alexzhirkevich.compottie.internal.AnimationState
import io.github.alexzhirkevich.compottie.internal.animation.RawProperty
import io.github.alexzhirkevich.compottie.internal.animation.expressions.EvaluationContext
import io.github.alexzhirkevich.compottie.internal.animation.expressions.Expression
import io.github.alexzhirkevich.compottie.internal.animation.expressions.operations.value.toExpressionType
import io.github.alexzhirkevich.compottie.internal.effects.LayerEffect
import io.github.alexzhirkevich.compottie.internal.layers.Layer

Expand All @@ -18,7 +16,7 @@ internal class OpGetEffect(
property: RawProperty<Any>,
context: EvaluationContext,
state: AnimationState
): Any {
): LayerEffect {
return invoke(
layer(property, context, state) as Layer,
nameOrIndex(property, context, state),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@ package io.github.alexzhirkevich.compottie.internal.animation.expressions.operat
import io.github.alexzhirkevich.compottie.internal.AnimationState
import io.github.alexzhirkevich.compottie.internal.animation.RawProperty
import io.github.alexzhirkevich.compottie.internal.animation.expressions.EvaluationContext
import io.github.alexzhirkevich.compottie.internal.animation.expressions.ExpressionComposition
import io.github.alexzhirkevich.compottie.internal.animation.expressions.Expression
import io.github.alexzhirkevich.compottie.internal.animation.expressions.ExpressionComposition
import io.github.alexzhirkevich.compottie.internal.layers.Layer

internal class OpGetLayer(
private val comp : Expression? = null,
Expand All @@ -15,7 +16,7 @@ internal class OpGetLayer(
property: RawProperty<Any>,
context: EvaluationContext,
state: AnimationState
): Any {
): Layer {
return if (nameOrIndex == null) {
state.layer
} else {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package io.github.alexzhirkevich.compottie.internal.animation.expressions.operations.composition

import io.github.alexzhirkevich.compottie.internal.AnimationState
import io.github.alexzhirkevich.compottie.internal.animation.AnimatedTransform
import io.github.alexzhirkevich.compottie.internal.animation.RawProperty
import io.github.alexzhirkevich.compottie.internal.animation.expressions.EvaluationContext
import io.github.alexzhirkevich.compottie.internal.animation.expressions.Expression
Expand All @@ -14,7 +15,7 @@ internal class OpGetLayerTransform(
property: RawProperty<Any>,
context: EvaluationContext,
state: AnimationState
): Any {
): AnimatedTransform {
return (layer(property, context, state) as Layer).transform
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package io.github.alexzhirkevich.compottie.internal.animation.expressions.operations.composition

import io.github.alexzhirkevich.compottie.internal.AnimationState
import io.github.alexzhirkevich.compottie.internal.animation.RawProperty
import io.github.alexzhirkevich.compottie.internal.animation.expressions.EvaluationContext
import io.github.alexzhirkevich.compottie.internal.animation.expressions.Expression
import io.github.alexzhirkevich.compottie.internal.layers.ShapeLayer
import io.github.alexzhirkevich.compottie.internal.shapes.GroupShape
import io.github.alexzhirkevich.compottie.internal.shapes.Shape

internal class OpGetShape(
private val layerOrGroup : Expression,
private val name : Expression
) : OpShapeContext() {

override fun invoke(
property: RawProperty<Any>,
context: EvaluationContext,
state: AnimationState
): Shape {
val layerOrGroup = layerOrGroup(property, context, state)
val name = (name(property, context, state) as CharSequence).toString()

val shape = when (layerOrGroup){
is ShapeLayer -> {
layerOrGroup.shapesByName[name]
}
is GroupShape -> {
layerOrGroup.shapesByName[name]
}
else -> error("Can't get '$name' content of $layerOrGroup")
}

return checkNotNull(shape){
"Content '$name' wasn't found"
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import io.github.alexzhirkevich.compottie.internal.animation.expressions.Express
import io.github.alexzhirkevich.compottie.internal.animation.expressions.ExpressionContext
import io.github.alexzhirkevich.compottie.internal.animation.expressions.Undefined
import io.github.alexzhirkevich.compottie.internal.animation.expressions.argAt
import io.github.alexzhirkevich.compottie.internal.animation.expressions.checkArgs
import io.github.alexzhirkevich.compottie.internal.animation.expressions.argForNameOrIndex
import io.github.alexzhirkevich.compottie.internal.animation.expressions.checkArgs
import io.github.alexzhirkevich.compottie.internal.animation.expressions.checkArgsNotNull
import io.github.alexzhirkevich.compottie.internal.animation.expressions.operations.value.OpConstant
import io.github.alexzhirkevich.compottie.internal.layers.Layer
Expand Down Expand Up @@ -33,6 +33,13 @@ internal sealed class OpLayerContext : Expression, ExpressionContext<Layer> {
if (this is PrecompositionLayer) composition else Undefined
}

"content" -> {
checkArgs(args, 1, callable)
OpGetShape(
layerOrGroup = this,
name = args.argAt(0)
)
}
"active" -> withContext { _, _, s -> isActive(s) }
"enabled" -> withContext { _, _, s -> !isHidden(s) }
"hasParent" -> withContext { _, _, _ -> parentLayer != null }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ internal class OpLayerToComp(
property: RawProperty<Any>,
context: EvaluationContext,
state: AnimationState
): Any {
): List<Number> {
val t = time.takeIf { it !is OpGetTime }

return if (t == null) {
Expand All @@ -49,7 +49,7 @@ internal class OpLayerToComp(
layer: Layer,
point : Any,
state: AnimationState,
) : Any {
) : List<Number> {

val layerMatrix = layer.totalTransformMatrix(state)
val compMatrix = state.currentComposition.transformMatrix(state)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import io.github.alexzhirkevich.compottie.internal.animation.expressions.operati
import io.github.alexzhirkevich.compottie.internal.animation.expressions.operations.time.OpGetTime
import io.github.alexzhirkevich.compottie.internal.layers.Layer
import io.github.alexzhirkevich.compottie.internal.layers.totalTransformMatrix
import io.github.alexzhirkevich.compottie.internal.utils.fastSetFrom

internal class OpLayerToWorld(
private val layer : Expression,
Expand All @@ -25,7 +24,7 @@ internal class OpLayerToWorld(
property: RawProperty<Any>,
context: EvaluationContext,
state: AnimationState
): Any {
): List<Number> {
val t = time.takeIf { it !is OpGetTime }

return if (t == null) {
Expand All @@ -49,7 +48,7 @@ internal class OpLayerToWorld(
layer: Layer,
point : Any,
state: AnimationState,
) : Any {
) : List<Number> {
val layerMatrix = layer.totalTransformMatrix(state)

val offset = Offset(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
package io.github.alexzhirkevich.compottie.internal.animation.expressions.operations.composition

import io.github.alexzhirkevich.compottie.internal.animation.AnimatedProperty
import io.github.alexzhirkevich.compottie.internal.animation.expressions.Expression
import io.github.alexzhirkevich.compottie.internal.animation.expressions.ExpressionContext
import io.github.alexzhirkevich.compottie.internal.animation.expressions.Undefined
import io.github.alexzhirkevich.compottie.internal.animation.expressions.argAt
import io.github.alexzhirkevich.compottie.internal.animation.expressions.checkArgs
import io.github.alexzhirkevich.compottie.internal.animation.expressions.operations.unresolvedReference
import io.github.alexzhirkevich.compottie.internal.animation.expressions.operations.value.toExpressionType
import io.github.alexzhirkevich.compottie.internal.shapes.EllipseShape
import io.github.alexzhirkevich.compottie.internal.shapes.FillShape
import io.github.alexzhirkevich.compottie.internal.shapes.PathShape
import io.github.alexzhirkevich.compottie.internal.shapes.RectShape
import io.github.alexzhirkevich.compottie.internal.shapes.Shape
import io.github.alexzhirkevich.compottie.internal.shapes.TransformShape

internal abstract class OpShapeContext : ExpressionContext<Shape> {
override fun interpret(callable: String?, args: List<Expression>?): Expression? {
return if (args != null) {
when (callable) {
"content" -> {
checkArgs(args, 1, callable)
OpGetShape(
layerOrGroup = this,
name = args.argAt(0)
)
}

else -> null
}
} else {
when (callable) {
"size" -> OpShapeSize(this)
"position" -> OpShapePosition(this)
"color" -> OpShapeColor(this)
"path" -> OpShapePath(this)
"scale" -> OpTransformShapeProperty(this, TransformShape::scale, callable)
"rotation" -> OpTransformShapeProperty(this, TransformShape::rotation, callable)
"rotationX" -> OpTransformShapeProperty(this, TransformShape::rotationX, callable)
"rotationY" -> OpTransformShapeProperty(this, TransformShape::rotationY, callable)
"rotationZ" -> OpTransformShapeProperty(this, TransformShape::rotationZ, callable)
"skew" -> OpTransformShapeProperty(this, TransformShape::skew, callable)
"skewAxis" -> OpTransformShapeProperty(this, TransformShape::skewAxis, callable)
"opacity" -> OpTransformShapeProperty(this, TransformShape::opacity, callable)
else -> null
}
}
}
}

private fun OpShapeColor(
shape : Expression
) = Expression { property, context, state ->
val shape = shape(property, context, state)

if (shape is FillShape){
shape.color.interpolated(state).toExpressionType()
} else {
unresolvedReference("color", shape::class.simpleName)
}

}

private fun OpShapeSize(
shape : Expression
) = Expression { property, context, state ->
val size = when (val shape = shape(property, context, state)){
is EllipseShape -> shape.size
is RectShape -> shape.size
else -> unresolvedReference("size", shape::class.simpleName)
}
size.interpolated(state).toExpressionType()
}

private fun OpShapePosition(
shape : Expression
) = Expression { property, context, state ->
val position = when (val shape = shape(property, context, state)){
is EllipseShape -> shape.position
is RectShape -> shape.position
is TransformShape -> shape.position
else -> unresolvedReference("position", shape::class.simpleName)
}
position.interpolated(state).toExpressionType()
}

private fun OpTransformShapeProperty(
shape: Expression,
property : (TransformShape) -> AnimatedProperty<*>?,
name : String
) = Expression { property, context, state ->
val value = when (val shape = shape(property, context, state)) {
is TransformShape -> property(shape)
else -> unresolvedReference(name, shape::class.simpleName)
}
value?.interpolated(state)?.toExpressionType() ?: Undefined
}


private fun OpShapePath(
shape : Expression
) = Expression { property, context, state ->
val shape = shape(property, context, state)
if(shape is PathShape) {
shape.shape.interpolated(state).toExpressionType()
} else {
unresolvedReference("path", shape::class.simpleName)
}
}
Loading

0 comments on commit 6ab2e59

Please sign in to comment.