Skip to content

Commit

Permalink
feat: 🎸 added interactivity support (#28)
Browse files Browse the repository at this point in the history
* feat: 🎸 added interactivity support

* chore: 🤖 removed a log
  • Loading branch information
afsalz authored Jun 26, 2024
1 parent 110e45f commit be646ff
Show file tree
Hide file tree
Showing 14 changed files with 1,149 additions and 89 deletions.
2 changes: 1 addition & 1 deletion dotlottie/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ plugins {
}

group = "com.github.LottieFiles"
version = "0.3.1"
version = "0.4.0"

android {
namespace = "com.lottiefiles.dotlottie.core"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,31 +1,46 @@
package com.lottiefiles.dotlottie.core.compose.runtime

import com.dotlottie.dlplayer.DotLottiePlayer
import com.dotlottie.dlplayer.Event
import com.dotlottie.dlplayer.Fit
import com.dotlottie.dlplayer.Layout
import com.dotlottie.dlplayer.Manifest
import com.dotlottie.dlplayer.Marker
import com.dotlottie.dlplayer.Mode
import com.dotlottie.dlplayer.Observer
import com.dotlottie.dlplayer.StateMachineObserver
import com.lottiefiles.dotlottie.core.util.DotLottieEventListener
import com.lottiefiles.dotlottie.core.util.LayoutUtil
import com.lottiefiles.dotlottie.core.util.StateMachineEventListener
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow

enum class DotLottiePlayerState {
PLAYING,
PAUSED,
STOPPED,
COMPLETED,
INITIAL,
LOADED,
ERROR,
}

class DotLottieController {
private var dlplayer: DotLottiePlayer? = null
private var observer: Observer? = null

private val _isRunning = MutableStateFlow(false)
val isRunning: StateFlow<Boolean> = _isRunning.asStateFlow()
private val _currentState = MutableStateFlow(DotLottiePlayerState.INITIAL)
val currentState: StateFlow<DotLottiePlayerState> = _currentState.asStateFlow()

private val _width = MutableStateFlow(0u)
val width: StateFlow<UInt> = _width.asStateFlow()

private val _height = MutableStateFlow(0u)
val height: StateFlow<UInt> = _height.asStateFlow()

var stateMachineListeners: MutableList<StateMachineEventListener> = mutableListOf()
private set
var eventListeners = mutableListOf<DotLottieEventListener>()
private set

Expand Down Expand Up @@ -94,7 +109,7 @@ class DotLottieController {
private fun subscribe() {
observer = object : Observer {
override fun onComplete() {
_isRunning.value = false
_currentState.value = DotLottiePlayerState.COMPLETED
eventListeners.forEach(DotLottieEventListener::onComplete)
}

Expand All @@ -103,22 +118,22 @@ class DotLottieController {
}

override fun onPause() {
_isRunning.value = false
_currentState.value = DotLottiePlayerState.PAUSED
eventListeners.forEach(DotLottieEventListener::onPause)
}

override fun onStop() {
_isRunning.value = false
_currentState.value = DotLottiePlayerState.STOPPED
eventListeners.forEach(DotLottieEventListener::onStop)
}

override fun onPlay() {
_isRunning.value = true
_currentState.value = DotLottiePlayerState.PLAYING
eventListeners.forEach(DotLottieEventListener::onPlay)
}

override fun onLoad() {
_isRunning.value = dlplayer?.isPlaying() ?: false
_currentState.value = DotLottiePlayerState.LOADED
eventListeners.forEach(DotLottieEventListener::onLoad)
}

Expand All @@ -131,12 +146,53 @@ class DotLottieController {
}

override fun onLoadError() {
_currentState.value = DotLottiePlayerState.ERROR
eventListeners.forEach(DotLottieEventListener::onLoadError)
}
}
dlplayer?.subscribe(observer!!)
}

fun startStateMachine(): Boolean {
val result = dlplayer?.startStateMachine() ?: false
if (result) {
dlplayer?.stateMachineSubscribe(object : StateMachineObserver {
override fun onStateEntered(enteringState: String) {
stateMachineListeners.forEach { it.onStateEntered(enteringState) }
}

override fun onStateExit(leavingState: String) {
stateMachineListeners.forEach { it.onStateExit(leavingState) }
}

override fun onTransition(previousState: String, newState: String) {
stateMachineListeners.forEach { it.onTransition(previousState, newState) }
}
})
}
return result
}

fun stopStateMachine(): Boolean {
return dlplayer?.stopStateMachine() ?: false
}

fun loadStateMachine(stateMachineId: String): Boolean {
return dlplayer?.loadStateMachine(stateMachineId) ?: false
}

fun postEvent(event: Event): Boolean {
return dlplayer?.postEvent(event) ?: false
}

fun addStateMachineEventListener(listener: StateMachineEventListener) {
stateMachineListeners.add(listener)
}

fun removeStateMachineEventListener(listener: StateMachineEventListener) {
stateMachineListeners.remove(listener)
}

fun setPlayerInstance(player: DotLottiePlayer) {
dlplayer?.destroy()
dlplayer = player
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ fun DotLottieAnimation(
var bufferBytes by remember { mutableStateOf<ByteBuffer?>(null) }
var imageBitmap by remember { mutableStateOf<ImageBitmap?>(null) }
val choreographer = remember { Choreographer.getInstance() }
val isRunning by rController.isRunning.collectAsState()
val currentSate by rController.currentState.collectAsState()
val _width by rController.height.collectAsState()
val _height by rController.width.collectAsState()
var layoutSize by remember { mutableStateOf<Size?>(null) }
Expand All @@ -101,7 +101,7 @@ fun DotLottieAnimation(
}
}

if (isRunning) {
if (dlPlayer.isPlaying()) {
choreographer.postFrameCallback(this)
}
}
Expand Down Expand Up @@ -140,7 +140,7 @@ fun DotLottieAnimation(
val startTime = System.currentTimeMillis()
val timeout = 500L // 500 milliseconds
while (isActive && System.currentTimeMillis() - startTime < timeout) {
if (System.currentTimeMillis() - startTime > 100L && !isRunning) {
if (System.currentTimeMillis() - startTime > 100L && !dlPlayer.isPlaying()) {
choreographer.removeFrameCallback(frameCallback)
break
}
Expand All @@ -153,8 +153,8 @@ fun DotLottieAnimation(
}
}

LaunchedEffect(isRunning) {
if (isRunning) {
LaunchedEffect(dlPlayer.isPlaying(), currentSate) {
if (dlPlayer.isPlaying()) {
choreographer.postFrameCallback(frameCallback)
} else {
choreographer.removeFrameCallback(frameCallback)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,14 @@ import androidx.annotation.FloatRange
import com.lottiefiles.dotlottie.core.util.DotLottieEventListener
import com.dotlottie.dlplayer.DotLottiePlayer
import com.dotlottie.dlplayer.Config
import com.dotlottie.dlplayer.Event
import com.dotlottie.dlplayer.Layout
import com.dotlottie.dlplayer.Manifest
import com.dotlottie.dlplayer.Marker
import com.dotlottie.dlplayer.Mode
import com.dotlottie.dlplayer.StateMachineObserver
import com.lottiefiles.dotlottie.core.util.DotLottieContent
import com.lottiefiles.dotlottie.core.util.StateMachineEventListener
import com.sun.jna.Pointer

class DotLottieDrawable(
Expand All @@ -31,6 +34,7 @@ class DotLottieDrawable(
private var nativeBuffer: Pointer? = null
private var bitmapBuffer: Bitmap? = null
private var dlPlayer: DotLottiePlayer? = null
private var stateMachineListeners: MutableList<StateMachineEventListener> = mutableListOf()

var freeze: Boolean = false
set(value) {
Expand Down Expand Up @@ -249,6 +253,47 @@ class DotLottieDrawable(
mHandler.removeCallbacks(mNextFrameRunnable)
}


fun startStateMachine(): Boolean {
val result = dlPlayer?.startStateMachine() ?: false
if (result) {
dlPlayer?.stateMachineSubscribe(object : StateMachineObserver {
override fun onStateEntered(enteringState: String) {
stateMachineListeners.forEach { it.onStateEntered(enteringState) }
}

override fun onStateExit(leavingState: String) {
stateMachineListeners.forEach { it.onStateExit(leavingState) }
}

override fun onTransition(previousState: String, newState: String) {
stateMachineListeners.forEach { it.onTransition(previousState, newState) }
}
})
}
return result
}

fun stopStateMachine(): Boolean {
return dlPlayer?.stopStateMachine() ?: false
}

fun loadStateMachine(stateMachineId: String): Boolean {
return dlPlayer?.loadStateMachine(stateMachineId) ?: false
}

fun postEvent(event: Event): Boolean {
return dlPlayer?.postEvent(event) ?: false
}

fun addStateMachineEventListener(listener: StateMachineEventListener) {
stateMachineListeners.add(listener)
}

fun removeStateMachineEventListener(listener: StateMachineEventListener) {
stateMachineListeners.remove(listener)
}

override fun draw(canvas: Canvas) {
if (bitmapBuffer == null || dlPlayer == null) return

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.lottiefiles.dotlottie.core.util

import com.dotlottie.dlplayer.StateMachineObserver

interface StateMachineEventListener : StateMachineObserver {
override fun onStateEntered(enteringState: String) {}

override fun onStateExit(leavingState: String) {}

override fun onTransition(previousState: String, newState: String) {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,13 @@ import android.graphics.drawable.Drawable
import android.util.AttributeSet
import android.view.View
import androidx.annotation.FloatRange
import com.dotlottie.dlplayer.Event
import com.dotlottie.dlplayer.Fit
import com.dotlottie.dlplayer.Layout
import com.dotlottie.dlplayer.Manifest
import com.dotlottie.dlplayer.Marker
import com.dotlottie.dlplayer.Mode
import com.dotlottie.dlplayer.StateMachineObserver
import com.dotlottie.dlplayer.createDefaultLayout
import com.lottiefiles.dotlottie.core.R
import com.lottiefiles.dotlottie.core.drawable.DotLottieDrawable
Expand All @@ -21,6 +23,7 @@ import com.lottiefiles.dotlottie.core.util.DotLottieEventListener
import com.lottiefiles.dotlottie.core.util.DotLottieSource
import com.lottiefiles.dotlottie.core.util.DotLottieUtils
import com.lottiefiles.dotlottie.core.util.LayoutUtil
import com.lottiefiles.dotlottie.core.util.StateMachineEventListener
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob
Expand Down Expand Up @@ -334,6 +337,31 @@ class DotLottieAnimation @JvmOverloads constructor(
mDotLottieEventListener.remove(listener)
}


fun startStateMachine(): Boolean {
return mLottieDrawable?.startStateMachine() ?: false
}

fun stopStateMachine(): Boolean {
return mLottieDrawable?.stopStateMachine() ?: false
}

fun loadStateMachine(stateMachineId: String): Boolean {
return mLottieDrawable?.loadStateMachine(stateMachineId) ?: false
}

fun postEvent(event: Event): Boolean {
return mLottieDrawable?.postEvent(event) ?: false
}

fun addStateMachineEventListener(listener: StateMachineEventListener) {
mLottieDrawable?.addStateMachineEventListener(listener)
}

fun removeStateMachineEventListener(listener: StateMachineEventListener) {
mLottieDrawable?.removeStateMachineEventListener(listener)
}

companion object {
private const val TAG = "DotLottieAnimation"

Expand Down
Binary file not shown.
Binary file not shown.
Binary file modified dotlottie/src/main/jniLibs/x86_64/libuniffi_dotlottie_player.so
Binary file not shown.
Loading

0 comments on commit be646ff

Please sign in to comment.