Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
Zhirkevich Alexander Y authored and Zhirkevich Alexander Y committed Jul 15, 2024
1 parent 67f348c commit cf9bca0
Show file tree
Hide file tree
Showing 18 changed files with 652 additions and 278 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -430,27 +430,8 @@ internal class AnimatedVectorGroup internal constructor(
* Child Vector nodes that are part of this group, this can contain
* paths or other groups
*/
private val children: List<AnimatedVectorNode> = emptyList()
) : AnimatedVectorNode(), Iterable<AnimatedVectorNode> {

val size: Int
get() = children.size

operator fun get(index: Int): AnimatedVectorNode {
return children[index]
}

override fun iterator(): Iterator<AnimatedVectorNode> {
return object : Iterator<AnimatedVectorNode> {

val it = children.iterator()

override fun hasNext(): Boolean = it.hasNext()

override fun next(): AnimatedVectorNode = it.next()
}
}
}
val children: List<AnimatedVectorNode> = emptyList()
) : AnimatedVectorNode()

/**
* Leaf node of a Vector graphics tree. This specifies a path shape and parameters
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package io.github.alexzhirkevich.compottie.avp

import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.DefaultAlpha
import androidx.compose.ui.graphics.Matrix
import androidx.compose.ui.graphics.Paint
Expand All @@ -22,24 +23,36 @@ import androidx.compose.ui.graphics.vector.DefaultTrimPathStart
import androidx.compose.ui.graphics.vector.EmptyPath
import androidx.compose.ui.graphics.vector.VNode
import androidx.compose.ui.util.fastForEach
import io.github.alexzhirkevich.compottie.avp.animator.ColorData
import io.github.alexzhirkevich.compottie.avp.animator.StaticFloatAnimator
import io.github.alexzhirkevich.compottie.avp.animator.StaticPaintAnimator
import io.github.alexzhirkevich.compottie.avp.animator.StaticPathAnimator

internal val DefaultRotationAnimator = StaticFloatAnimator(DefaultRotation)
internal val DefaultPivotXAnimator = StaticFloatAnimator(DefaultPivotX)
internal val DefaultPivotYAnimator = StaticFloatAnimator(DefaultPivotY)
internal val DefaultScaleXAnimator = StaticFloatAnimator(DefaultScaleX)
internal val DefaultScaleYAnimator = StaticFloatAnimator(DefaultScaleY)
internal val DefaultTranslationXAnimator = StaticFloatAnimator(DefaultTranslationX)
internal val DefaultTranslationYAnimator = StaticFloatAnimator(DefaultTranslationY)
internal val EmptyPathAnimator = StaticPathAnimator(EmptyPath)

internal val DefaultTrimPathStartAnimator = StaticFloatAnimator(DefaultTrimPathStart)
internal val DefaultTrimPathEndAnimator = StaticFloatAnimator(DefaultTrimPathEnd)
internal val DefaultTrimPathOffsetAnimator = StaticFloatAnimator(DefaultTrimPathOffset)
internal val DefaultStrokeLineMiterAnimator = StaticFloatAnimator(DefaultStrokeLineMiter)
internal val DefaultStrokeLineWidthAnimator = StaticFloatAnimator(DefaultStrokeLineWidth)
internal val DefaultAlphaAnimator = StaticFloatAnimator(DefaultAlpha)
import io.github.alexzhirkevich.compottie.avp.xml.AnimatedVectorProperty

internal val DefaultRotationAnimator = StaticFloatAnimator(DefaultRotation, AnimatedVectorProperty.Rotation)
internal val DefaultPivotXAnimator = StaticFloatAnimator(DefaultPivotX, AnimatedVectorProperty.PivotX)
internal val DefaultPivotYAnimator = StaticFloatAnimator(DefaultPivotY, AnimatedVectorProperty.PivotY)
internal val DefaultScaleXAnimator = StaticFloatAnimator(DefaultScaleX, AnimatedVectorProperty.ScaleX)
internal val DefaultScaleYAnimator = StaticFloatAnimator(DefaultScaleY, AnimatedVectorProperty.ScaleY)
internal val DefaultTranslationXAnimator = StaticFloatAnimator(DefaultTranslationX, AnimatedVectorProperty.TranslationX)
internal val DefaultTranslationYAnimator = StaticFloatAnimator(DefaultTranslationY, AnimatedVectorProperty.TranslationY)
internal val EmptyPathAnimator = StaticPathAnimator(EmptyPath, AnimatedVectorProperty.PathData)
internal val TransparentFillColorAnimator = StaticPaintAnimator(
ColorData.Solid(Color.Transparent),
AnimatedVectorProperty.FillColor
)
internal val TransparentStrokeColorAnimator = StaticPaintAnimator(
ColorData.Solid(Color.Transparent),
AnimatedVectorProperty.StrokeColor
)

internal val DefaultTrimPathStartAnimator = StaticFloatAnimator(DefaultTrimPathStart, AnimatedVectorProperty.TrimPathStart)
internal val DefaultTrimPathEndAnimator = StaticFloatAnimator(DefaultTrimPathEnd, AnimatedVectorProperty.TrimPathEnd)
internal val DefaultTrimPathOffsetAnimator = StaticFloatAnimator(DefaultTrimPathOffset, AnimatedVectorProperty.TrimPathOffset)
internal val DefaultStrokeLineMiterAnimator = StaticFloatAnimator(DefaultStrokeLineMiter, AnimatedVectorProperty.StrokeLineMiter)
internal val DefaultStrokeLineWidthAnimator = StaticFloatAnimator(DefaultStrokeLineWidth, AnimatedVectorProperty.StrokeLineWidth)
internal val DefaultFillAlphaAnimator = StaticFloatAnimator(DefaultAlpha, AnimatedVectorProperty.FillAlpha)
internal val DefaultStrokeAlphaAnimator = StaticFloatAnimator(DefaultAlpha, AnimatedVectorProperty.StrokeAlpha)

internal sealed class AnimatedVNode {

Expand Down Expand Up @@ -131,9 +144,15 @@ internal class AnimatedPathComponent(
internal class AnimatedGroupComponent(
private val group: AnimatedVectorGroup
) : AnimatedVNode() {

private var groupMatrix: Matrix? = null

private val children = mutableListOf<VNode>()
private val children = group.children.map {
when (it) {
is AnimatedVectorGroup -> AnimatedGroupComponent(it)
is AnimatedVectorPath -> AnimatedPathComponent(it)
}
}

private val willClipPath: Boolean
get() = group.clipPathData !is StaticPathAnimator || group.clipPathData.value.isNotEmpty()
Expand Down Expand Up @@ -173,7 +192,7 @@ internal class AnimatedGroupComponent(
}) {
children.fastForEach { node ->
with(node) {
this@draw.draw()
draw(time)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,34 +1,64 @@
@file: Suppress("INVISIBLE_MEMBER","INVISIBLE_REFERENCE")

package io.github.alexzhirkevich.compottie.avp

import androidx.compose.runtime.Composable
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.getValue
import androidx.compose.runtime.produceState
import androidx.compose.ui.Alignment
import androidx.compose.ui.geometry.Size
import androidx.compose.ui.graphics.drawscope.DrawScope
import androidx.compose.ui.graphics.drawscope.scale
import androidx.compose.ui.graphics.drawscope.translate
import androidx.compose.ui.graphics.painter.Painter
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.unit.Density
import androidx.compose.ui.unit.DpSize
import androidx.compose.ui.unit.IntSize
import io.github.alexzhirkevich.compottie.avp.animator.ObjectAnimator
import org.jetbrains.compose.resources.DefaultComposeEnvironment
import io.github.alexzhirkevich.compottie.avp.xml.toAnimatedImageVector
import org.jetbrains.compose.resources.DrawableResource
import org.jetbrains.compose.resources.ExperimentalResourceApi
import org.jetbrains.compose.resources.InternalResourceApi
import org.jetbrains.compose.resources.getResourceItemByEnvironment
import org.jetbrains.compose.resources.LocalComposeEnvironment
import org.jetbrains.compose.resources.LocalResourceReader
import org.jetbrains.compose.resources.toXmlElement
import kotlin.math.roundToInt



@OptIn(ExperimentalResourceApi::class, InternalResourceApi::class)
@Composable
public fun rememberAnimatedVectorPainter(
resource : DrawableResource,
animations : List<ObjectAnimator<*,*>>,
isAtAnd : Boolean
) : Painter {
val environment = LocalComposeEnvironment.cu
val environment = LocalComposeEnvironment.current.rememberEnvironment()
val path = resource.getResourceItemByEnvironment(environment).path

val density = LocalDensity.current
val resourceReader = LocalResourceReader.current

val painter by produceState<Painter>(EmptyPainter, density) {
val image = resourceReader.read(path).toXmlElement()
val vector = image.toAnimatedImageVector(density, emptyMap())
value = AnimatedVectorPainter(
vector,
density,
{ 0f }
)
}
return painter
}

private object EmptyPainter : Painter() {
override val intrinsicSize: Size = Size(1f,1f)

override fun DrawScope.onDraw() {
}

}


Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package io.github.alexzhirkevich.compottie.avp

public class AnimationTarget(
public val name : String,
public val animation: String
)

public class AnimatedVector(
public val animations : List<AnimationTarget>
)

Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
package io.github.alexzhirkevich.compottie.avp.animator

import io.github.alexzhirkevich.compottie.avp.AnimatedVector

public interface AnimatorSpec {

public suspend fun load() : ObjectAnimator<*,*>
public suspend fun load(
animatedVector: AnimatedVector
): Map<String, ObjectAnimator<*, *>>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
package io.github.alexzhirkevich.compottie.avp.animator

import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.LinearGradientShader
import androidx.compose.ui.graphics.RadialGradientShader
import androidx.compose.ui.graphics.Shader
import androidx.compose.ui.graphics.SweepGradientShader
import androidx.compose.ui.graphics.TileMode

public sealed interface ColorData {

public sealed class GradientColorData : ColorData {

public abstract val colorStops: List<Pair<Float, Color>>

protected val colors : List<Color> get() = mColors

protected val stops : List<Float> get() = mStops


private val mColors by lazy {
colorStops.map { it.second }.toMutableList()
}

private val mStops by lazy {
colorStops.map { it.first }.toMutableList()
}

internal abstract val shader : Shader

internal abstract fun lerpShader(other : GradientColorData, progress: Float) : Shader

protected fun lerpColorStops(other: GradientColorData, progress: Float) {
require(other.colorStops.size == colorStops.size){
repeat(colorStops.size) {
mColors[it] = androidx.compose.ui.graphics.lerp(
colorStops[it].second,
other.colorStops[it].second,
progress
)
mStops[it] = androidx.compose.ui.util.lerp(
colorStops[it].first,
other.colorStops[it].first,
progress
)
}
}
}
}

public class Solid(public val color: Color) : ColorData

public class LinearGradient(
override val colorStops : List<Pair<Float, Color>>,
public val start : Offset,
public val end : Offset,
public val tileMode: TileMode
) : GradientColorData() {

override val shader: Shader by lazy {
LinearGradientShader(
from = start,
to = end,
colors = colors,
colorStops = stops
)
}

override fun lerpShader(other: GradientColorData, progress: Float): Shader {
other as LinearGradient
lerpColorStops(other, progress)

return LinearGradientShader(
from = androidx.compose.ui.geometry.lerp(start, other.start, progress),
to = androidx.compose.ui.geometry.lerp(end, other.end, progress),
colors = colors,
colorStops = stops,
tileMode = other.tileMode
)
}
}

public class RadialGradient(
override val colorStops : List<Pair<Float, Color>>,
public val center : Offset,
public val radius : Float,
public val tileMode: TileMode
) : GradientColorData() {

override val shader: Shader by lazy {
RadialGradientShader(
center = center,
radius = radius,
colors = colors,
colorStops = stops
)
}

override fun lerpShader(other: GradientColorData, progress: Float): Shader {
other as RadialGradient
lerpColorStops(other, progress)

return RadialGradientShader(
center = androidx.compose.ui.geometry.lerp(center, other.center, progress),
radius = androidx.compose.ui.util.lerp(radius, other.radius, progress),
colors = colors,
colorStops = stops,
tileMode = other.tileMode
)
}
}

public class SweepGradient(
override val colorStops : List<Pair<Float, Color>>,
public val center : Offset,
) : GradientColorData() {

override val shader: Shader by lazy {
SweepGradientShader(
center = center,
colors = colors,
colorStops = stops
)
}

override fun lerpShader(other: GradientColorData, progress: Float): Shader {
other as SweepGradient
lerpColorStops(other, progress)

return SweepGradientShader(
center = androidx.compose.ui.geometry.lerp(center, other.center, progress),
colors = colors,
colorStops = stops,
)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package io.github.alexzhirkevich.compottie.avp.animator

import androidx.compose.animation.core.Easing
import androidx.compose.animation.core.LinearEasing
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import io.github.alexzhirkevich.compottie.avp.xml.AnimatedVectorProperty

@Composable
public fun rememberNumberAnimator(
duration: Float,
valueFrom: Float,
valueTo: Float,
property: AnimatedVectorProperty<FloatAnimator>,
delay : Float = 0f,
interpolator: Easing = LinearEasing,
) : FloatAnimator {
return remember(duration, valueFrom, valueTo, property, delay, interpolator) {
FloatAnimator(duration, valueFrom, valueTo, property, delay, interpolator)
}
}
Loading

0 comments on commit cf9bca0

Please sign in to comment.